11 Replies Latest reply on Nov 6, 2009 6:45 PM by Jubril Adisa

    JasperReports + Seam

    Francisco Jose Peredo Noguez Master

      Hi!


      Is it possible (and not extremely hard) to integrate Seam and Jasper Reports? Is there a way to somewhat make a JasperReport get the data model (outjected? injected?) in pretty much the same way Spring does it?


      Or do you think is better to use the Seam/Spring integration to do this kind of work (using report engines like Jasper Reports)?


      Thanks


      Regards,

        • 1. Re: JasperReports + Seam
          Daniel Young Novice

          Hi Francisco,


          My Seam project is using JasperReports quite heavily, but there was nothing with Seam that really made the integration easier.  It took a fair bit of code to set up, but works very well now that it's all there.  I'll give you a brief overview of the approach I used, and let you decide if the Spring way is easier:


          1) I created a SimpleReportSource class which extends JRAbstractBeanDataSource, takes an EJB3 query and exposes the results to a Jasper report.


          2) I have a Report abstract class that handles filling a jasper report (jrxml) based on the results of an abstract template method getQuery(), which the subclasses define.


          3) I wrote a custom JSF component (sp:report / UIReport.java) that I use in my facelets pages.  It gets report input parameters (filters) from the user interface and passes them to the appropriate Report class.  In its encodeEnd() method, it uses the JRHtmlExporter() to export the report as HTML and writes this into the response, using FacesContext.getResponseWriter().  This allows previewing of the report as embedded HTML.  It also contains an export() command that allows exporting to different formats (PDF, RTF, etc) and writes that to the response with a Content-Disposition / attachment; header so it opens in a new window.


          As you can see that's quite alot of stuff to get working, and I didn't get much help from Seam along the way.  There may be other designs that allow you to do the work inside a Seam component rather than writing a JSF component.


          I have considered submitting the code for this, because I think it would be really useful for others.  So far I haven't had the time or been able to get permission from my employer.


          I hope this long answer is some help to you!


          cheers,
          Daniel.

          • 2. Re: JasperReports + Seam
            Rodolfo Jarquin Newbie

            Daniel can you send me please a source code sample of your seam-jaspperreport component ?


            Thank you.


            Rodolfo J.

            • 3. Re: JasperReports + Seam
              Eric Poiseau Newbie

              Daniel


              please could you send me a sample of your seam-jaspperreport component too ?


              Thanks



              • 4. Re: JasperReports + Seam
                Markus Öllinger Newbie

                The simplest way to do this is have a servlet show the report in a separate window outside of JSF. You'll still have Seam involved but not JSF. This makes it possible to output the results of the report directly to the page. This is perfect for generating reports for printout from a web based application.


                If you rather want reports embedded into the page itself, then you need to write tags. In this case, you're better off when you are working with facelets instead of JSP as the base platform for your JSF. In this case, you can write a facelets tag which is much simpler than a full-fledged JSF tag. I've done this too but in this post, I'll describe the Servlet approach.



                • Define a new Servlet in web.xml:



                     <servlet>
                          <servlet-name>Direct Seam Servlet</servlet-name>
                          <servlet-class>yourpackage.SeamServletAdapter</servlet-class>
                     </servlet>
                     <servlet-mapping>
                          <servlet-name>Direct Seam Servlet</servlet-name>
                          <url-pattern>/seam/servlet/*</url-pattern>
                     </servlet-mapping>
                




                • in components.xml you have to enable Seam for the new URL pattern:



                   <!-- enable Seam for this non-JSF URL pattern -->
                   <web:context-filter url-pattern="/seam/servlet/*"/>
                




                • Write the servlet class in your web project. All this servlet does is forward the request to a Seam component (i.e. it's an adapter):



                public class SeamServletAdapter extends HttpServlet {
                     private static final long serialVersionUID=8830027561411226041L;
                
                     @Override
                     protected void service(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {
                          String componentName=request.getParameter("component");
                          if(componentName==null) {
                               String path=request.getRequestURI();
                               int index=path.lastIndexOf('/');
                               if(index>=0)
                                    componentName=path.substring(index+1);
                               if(componentName.endsWith(".seam"))
                                    componentName=componentName.substring(0,componentName.length()-".seam".length());
                          }
                          try {
                               delegateToSeamComponent(request,response,componentName);
                          }
                          catch(Exception e) {
                               if(IOException.class.isAssignableFrom(e.getClass()))
                                    throw (IOException)e;
                               if(ServletException.class.isAssignableFrom(e.getClass()))
                                    throw (ServletException)e;
                               throw new ServletException("could not call Seam component "+componentName,e);
                          }
                     }
                
                     private void delegateToSeamComponent(HttpServletRequest request,HttpServletResponse response,String componentName)
                               throws NoSuchMethodException,IllegalAccessException,InvocationTargetException {
                          Object component=Component.getInstance(componentName);
                          Method method=component.getClass().getMethod("service",HttpServletRequest.class,HttpServletResponse.class);
                          method.invoke(component,request,response);
                     }
                
                }
                




                • Our Seam component printSomething then can handle the request in its service method. Note that it also passes on a Seam managed EntityManager to the JasperReports report which can use it to perform EJB queries if you use the corresp. DataSource in the report. If you are doing SQL queries in your report, then you don't have to do this, ofc.



                     @In
                     private EntityManager entityManager;
                
                     public void service(HttpServletRequest request,HttpServletResponse response) throws JRException,IOException,
                               ServletException {
                          JasperReport jasperReport=getJasperReport();
                          Map<String, Object> params=new HashMap<String, Object>();
                          convertRequestParameters(jasperReport,request.getParameterMap(),params);
                          params.put("SUBREPORT_DIR","reports/");
                          params.put(JRJpaQueryExecuterFactory.PARAMETER_JPA_ENTITY_MANAGER,entityManager);
                          JasperPrint jasperPrint=JasperFillManager.fillReport(jasperReport,params);
                          response.setContentType("application/pdf");
                          OutputStream out=response.getOutputStream();
                          JRPdfExporter exporter=new JRPdfExporter();
                          exporter.setParameter(JRExporterParameter.JASPER_PRINT,jasperPrint);
                          exporter.setParameter(JRExporterParameter.OUTPUT_STREAM,out);
                          try {
                               exporter.exportReport();
                          }
                          finally {
                               out.close();
                          }
                     }
                




                • In the above method, we have the format hardcoded to pdf for the sake of simplicity. Parameters for the report during the fill process should be passed to the Servlet as request parameters. These need to be converted to JasperReports parameters. Note that you can't use @RequestParameter in your Seam component as it is outside of JSF and has no FacesContext, so we use the following method to convert the request parameters to jasper:



                     public static void convertRequestParameters(JasperReport jasperReport,Map<String, String[]> requestParameterMap,
                               Map<String, Object> jrParameterMap) {
                          JRParameter[] params=jasperReport.getParameters();
                          for(JRParameter p : params) {
                               String[] values=requestParameterMap.get(p.getName());
                               if(values==null||values.length==0) continue; // parameter not provided
                               Object o;
                               if(!p.getValueClass().equals(String.class)) // convert string to desired type
                                    o=ConvertUtils.convert(values[0],p.getValueClass());
                               else o=values[0]; // String is expected and we have string, should be ok
                               jrParameterMap.put(p.getName(),o);
                          }
                     }
                




                • To insert this into a xhtml page, you can use the following excerpt:



                     <s:link view="/seam/servlet/" target="_blank">
                          <h:graphicImage value="/img/print.gif" />
                          <f:param name="component" value="printSomething"/>
                          <f:param name="someParam" value="#{t.someParam}" />
                     </s:link>
                



                Here, the printSomething Seam component will be called when clicking on the link. A new browser window will be opened and show the report.

                • 5. Re: JasperReports + Seam
                  Markus Öllinger Newbie

                  Writing a facelets tag is not complicated either, here is how you can do this:


                  Write a facelet tag description and put it into WEB-INF (or META-INF in a lib). Let's call it JasperReports.taglib.xml:


                  <?xml version="1.0" encoding="UTF-8"?>
                  <!DOCTYPE facelet-taglib PUBLIC
                    "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
                    "http://java.sun.com/dtd/facelet-taglib_1_0.dtd">
                  <facelet-taglib xmlns="http://java.sun.com/JSF/Facelet">
                       <namespace>http://jasperreports.sourceforge.net/jr</namespace>
                       <tag>
                            <tag-name>report</tag-name>
                            <component>
                                 <component-type>Report</component-type>
                                 <renderer-type>Report</renderer-type>
                            </component>
                       </tag>
                       <tag>
                            <tag-name>parameter</tag-name>
                            <handler-class>mypackage.ParameterTag</handler-class>
                       </tag>
                  </facelet-taglib>
                  



                  It's best to put this all into a library into META-INF and include it from your webapp. If you don't and put it directly into your webapp then you need to explicitly reference this from within your web.xml as a facelets.LIBRARIES context parameter.


                       <context-param>
                            <param-name>facelets.LIBRARIES</param-name>
                            <param-value>
                                 /WEB-INF/JasperReports.taglib.xml
                            </param-value>
                       </context-param>
                  



                  We'll need to create a JSF component and a renderer and register them in the faces-config.xml:


                  <?xml version="1.0" encoding="UTF-8"?>
                  <faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xi="http://www.w3.org/2001/XInclude"
                       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
                       <!-- JasperReports JSF components -->
                       <component>
                            <component-type>Report</component-type>
                            <component-class>mypackage.ReportComponent</component-class>
                            <property>
                                 <description>Report to show.</description>
                                 <property-name>report</property-name>
                                 <property-class>java.lang.String</property-class>
                            </property>
                  
                            <component-extension>
                                 <component-family>Jasper</component-family>
                                 <renderer-type>Report</renderer-type>
                            </component-extension>
                  
                       </component>
                  
                       <render-kit>
                            <renderer>
                                 <description>JasperReports report renderer.</description>
                                 <component-family>Jasper</component-family>
                                 <renderer-type>Report</renderer-type>
                                 <renderer-class>mypackage.ReportRenderer</renderer-class>
                            </renderer>
                       </render-kit>
                  </faces-config>
                  



                  This is our JSF component:


                  public class ReportComponent extends UIComponentBase {
                       private static final Logger log=Logger.getLogger(ParameterTag.class);
                       /**Filename of the report.*/
                       private String report;
                       /**The report's parameters.*/
                       private Map<String,Object> parameters=new HashMap<String,Object>();
                       
                       public ReportComponent() {
                            log.info("creating ReportComponent");
                       }
                  
                       @Override
                       public String getFamily() {
                            return "Jasper";
                       }
                  
                       /**Returns the name of the report (which may include a path).*/
                       public String getReport() {
                            if(report==null) {
                                 ValueExpression ve=getValueExpression("report");
                                 if(ve!=null) {
                                      report=(String)ve.getValue(getFacesContext().getELContext());
                                 }
                            }
                            return report;
                       }
                  
                       public void setReport(String report) {
                            this.report=report;
                            log.info("setting report name to "+report);
                       }
                       
                       /**Add a new parameter to the report.*/
                       public void addParameter(String name,Object value) {
                            parameters.put(name,value);
                       }
                       
                       /**Get the map of report parameters.*/
                       public Map<String,Object> getParameters() {
                            return parameters;
                       }
                  
                       /**
                        * <p>
                        * Return the state to be saved for this component.
                        * </p>
                        * 
                        * @param context
                        *            <code>FacesContext</code> for the current request
                        */
                       public Object saveState(FacesContext context) {
                            Object[] values=new Object[3];
                            values[0]=super.saveState(context);
                            values[1]=report;
                            values[2]=parameters;
                  
                            return (values);
                       }
                  
                       /**
                        * <p>
                        * Restore the state for this component.
                        * </p>
                        * 
                        * @param context
                        *            <code>FacesContext</code> for the current request
                        * @param state
                        *            State to be restored
                        * 
                        * @throws IOException
                        *             if an input/output error occurs
                        */
                       @SuppressWarnings("unchecked")
                       public void restoreState(FacesContext context,Object state) {
                            Object[] values=(Object[])state;
                            super.restoreState(context,values[0]);
                            report=(String)values[1];
                            parameters=(Map<String,Object>)values[2];
                       }
                  
                       @Override
                       public String getRendererType() {
                            return "Report";
                       }
                  
                  }
                  



                  and this the associated renderer:


                  public class ReportRenderer extends Renderer {
                       private static final Logger log=Logger.getLogger(ReportRenderer.class);
                  
                       @Override
                       public void encodeEnd(FacesContext context,UIComponent component) throws IOException {
                            super.encodeEnd(context,component);
                            ResponseWriter writer=context.getResponseWriter();
                            try {
                                 ReportComponent reportComponent=(ReportComponent)component;
                                 String reportName=reportComponent.getReport();
                                 Map<String, Object> parameters=reportComponent.getParameters();
                                 String reportDir=reportName;
                                 int index=reportName.lastIndexOf('/');
                                 if(index>0) reportDir=reportName.substring(0,index+1);
                                 parameters=new HashMap<String, Object>(parameters); // TODO do we really need to copy this?
                                 parameters.put("SUBREPORT_DIR",reportDir);
                                 JasperReport jasperReport=getJasperReport(reportName);
                                 setSeamManagedEntityManager(parameters);
                                 JasperPrint jasperPrint=JasperFillManager.fillReport(jasperReport,parameters);
                                 JRHtmlExporter exporter=new JRHtmlExporter();
                                 exporter.setParameter(JRExporterParameter.JASPER_PRINT,jasperPrint);
                                 exporter.setParameter(JRExporterParameter.OUTPUT_WRITER,writer);
                                 exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI,"image?image=");
                  
                                 exporter.exportReport();
                            }
                            catch(JRException e) {
                                 log.error("could not generate report",e);
                                 PrintWriter out=new PrintWriter(writer);
                                 out.write("<span class=\"bnew\">JasperReports encountered this error :</span>\n");
                                 out.write("<pre>\n");
                                 e.printStackTrace(out);
                                 out.write("</pre>\n");
                            }
                       }
                  
                       /**
                        * Adds the Seam managed EntityManager to the given parameters if we have Seam on the classpath.
                        * 
                        * @param parameters
                        *            the parameters Map passed to JasperReports when filling the report.
                        */
                       private static void setSeamManagedEntityManager(Map<String, Object> parameters) {
                            try { // perform org.jboss.seam.Component.getInstance("entityManager") to get the EntityManager
                                 Class<?> clazz=Class.forName("org.jboss.seam.Component");
                                 Method getInstance=clazz.getMethod("getInstance",String.class);
                                 Object entityManager=getInstance.invoke(null,"entityManager");
                                 parameters.put(JRJpaQueryExecuterFactory.PARAMETER_JPA_ENTITY_MANAGER,entityManager);
                                 log.info("setting EntityManager "+entityManager);
                            }
                            catch(Exception e) {
                                 log.info("Seam not in the classpath or other problem, EntityManager not set");
                                 // silently ignore exception, probably "Seamless" environment
                            }
                       }
                  
                       /**
                        * Returns a JasperReport by its file name. If the report's jasper file is found then it is loaded and returned.
                        * Otherwise, we look for an jrxml file and compile it to the jasper file first.
                        * 
                        * @param reportName
                        *            the name of the JasperReport to return.
                        * @return the corresponding JasperReport ready to be filled.
                        * @throws JRException
                        *             if something went wrong.
                        */
                       public static JasperReport getJasperReport(String reportName) throws JRException {
                            String jasperFilename=reportName+".jasper";
                            if(jasperFilename.startsWith("/")) jasperFilename=jasperFilename.substring(1); // strip off leading slash
                            File file=new File(jasperFilename);
                            if(file.exists()) {
                                 log.info("loading jasper file from "+file.getPath());
                                 JasperReport jasperReport=(JasperReport)JRLoader.loadObject(jasperFilename);
                                 return jasperReport;
                            }
                            InputStream is=Thread.currentThread().getContextClassLoader().getResourceAsStream(reportName+".jrxml");
                            if(is==null) throw new JRException("could not open "+reportName+".jrxml");
                            log.info("loading jrxml file from "+reportName+" and compiling it to "+file.getPath());
                            JasperDesign design=JRXmlLoader.load(is);
                            JasperReport jasperReport=JasperCompileManager.compileReport(design);
                            JRSaver.saveObject(jasperReport,file);
                            return jasperReport;
                       }
                  
                  }
                  



                  We also need a parameter tag to pass parameters to JasperReports. We already defined this is our taglib but we still need to implement this:


                  public class ParameterTag extends TagHandler {
                       private static final Logger log=Logger.getLogger(ParameterTag.class);
                       /**Name of the JasperReport parameter.*/
                       private final TagAttribute name;
                       /**Value of the parameter.*/
                       private final TagAttribute value;
                       /**Type to coerce the value to (optional).*/
                       private final TagAttribute type;
                       
                       public ParameterTag(TagConfig config) {
                            super(config);
                            name=getRequiredAttribute("name");
                            value=getRequiredAttribute("value");
                            type=getAttribute("type");
                            log.debug("parameter "+name.getValue()+" value "+value.getValue());
                       }
                       /**Applies the parameters to our parent which should be an instance of ReportComponent.*/
                       public void apply(FaceletContext ctx,UIComponent parent) throws IOException,FacesException,FaceletException,
                                 ELException {
                            if(parent instanceof ReportComponent) {
                                 ReportComponent reportComponent=(ReportComponent)parent;
                                 Object o=value.getObject(ctx,getTypeClass(ctx));
                                 log.info("adding report parameter "+name.getValue()+" with value "+o+" of type "+o.getClass());
                                 reportComponent.addParameter(name.getValue(ctx),o);
                            }
                            else log.warn("parameter tag not inside a report tag!");
                            this.nextHandler.apply(ctx,parent);
                       }
                       /**Returns the type class the value should be cast to.*/
                       private Class<?> getTypeClass(FaceletContext ctx) {
                            try {
                                 if(type!=null) {
                                      Class<?> clazz=Class.forName(type.getValue(ctx));
                                      return clazz;
                                 }
                            }
                            catch(ClassNotFoundException e) {
                                 log.error("cannot convert report parameter "+name.getValue()+" to class "+type.getValue(),e);
                            }
                            return String.class;
                       }
                  
                  }
                  



                  We can then use this in a facelets based Seam/JSF page:


                       <jr:report report="reports/YourReport">
                            <jr:parameter name="someparam" value="#{someBean.someparam}" type="java.lang.Long"/>
                       </jr:report>
                  



                  As you can see, the report tag needs the name of the report (without jrxml/jasper suffix).
                  The enclosed parameter tags take the name, value and optional type. These parameters will be used when filling the above report.


                  These tags will insert the HTML report directly into the page.


                  Note that this does not work if you are JSP based, in this case you have to write JSP tags (tlds) and corresponding implementations, one for the parameter tag but also one for the report tag. I'll leave it to you to figure out how to do this.


                  Hope this helps.

                  • 6. Re: JasperReports + Seam
                    Francisco Jose Peredo Noguez Master

                    Very interesting solution! I will give it a shot later...
                    One thing though... it is not the simplest way to do this this one (while limited) is much simpler to implement (but it does get some help from org.springframework.ui.jasperreports.JasperReportsUtils):


                    public void printReport() throws JRException, IOException {
                              if (!this.facesContext.getResponseComplete()) {
                                   HttpServletResponse response = (HttpServletResponse) facesContext
                                             .getExternalContext().getResponse();
                                   
                                   response.setContentType("application/pdf");
                                  
                                   Map parameters = new HashMap(); 
                                   parameters.put("today",new Date());
                                                                                
                                   Object reportData = someEntityHome.getSomeEntityList();
                                   java.io.OutputStream stream = response.getOutputStream();
                                   
                                   JasperReport report = (JasperReport) JRLoader
                                             .loadObject(facesContext.getExternalContext()
                                                       .getResourceAsStream("/WEB-INF/reports/someReport.jasper"));
                                   JasperReportsUtils.renderAsPdf(report, parameters, reportData,
                                             stream);
                                   
                                   facesContext.responseComplete();
                              }
                         }
                    



                    A lot less code than your solution, but it, of course has its own limitations (it is not bookmarkable for example, it can not be embbeded in another page, etc, etc). But if you are in hurry it can help you.

                    • 7. Re: JasperReports + Seam
                      Markus Öllinger Newbie

                      You are right, I also started out with a solution similar to this one but then moved to the servlet based one for some reason. I am not totally happy with the servlet based though because you are outside of the JSF contect which causes some problems.


                      About being bookmarkable, the servlet-based one is indeed bookmarkable but only if you do not impose any security rules (which you often have to). Seam's security redirection (or the corresponding exception handler) does not work as it relies on Faces which is not there.


                      Please note that in the above code excerpts it throws an InvocationTargetException in this case (since service() is invoked using invoke) but even if you handle that and throw the enclosed NotLoggedInException, it does not redirect you, so you end up havin ugly exceptions in that case.


                      The second tag-based solution does not suffer from that of course, but it is more or less limited to HTML output (as it is embedded in a HTML page).

                      • 8. Re: JasperReports + Seam
                        Parimal Chauhan Newbie

                        Hi, I am working on jasper reports with the help first solution of this topic.
                        i have followed the steps shown above in the first solution.
                        (i.e
                        1)created ServletAdapter-SeamServletAdapter
                        2)configured web.xml,component.xml
                        3)created printSomething servlet with method shown above in this topic.
                        4) added link on xhtml as shown.


                        but i am getting an exception while clicking on the link on the page.that is ..


                         "java.lang.IllegalStateException: No active event context".




                        while debugging the application i found that the exception is thrown at the statement in the printSomething servlet


                         JRPdfExporter exporter=new JRPdfExporter(); 



                        here is the error stack trace..


                        13:32:18,510 ERROR [[Direct Seam Servlet]] Servlet.service() for servlet Direct
                        Seam Servlet threw exception
                        java.lang.IllegalStateException: No active event context
                                at org.jboss.seam.core.Manager.instance(Manager.java:368)
                                at org.jboss.seam.servlet.ContextualHttpServletRequest.run(ContextualHtt
                        pServletRequest.java:55)
                                at org.jboss.seam.web.ContextFilter.doFilter(ContextFilter.java:37)
                                at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter
                        .java:69)
                                at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:177)
                        
                                at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:267)
                                at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFil
                        ter.java:380)
                                at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:507)
                                at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:56)
                                at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter
                        .java:69)
                                at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:58)
                                at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter
                        .java:69)
                                at org.jboss.seam.web.HotDeployFilter.doFilter(HotDeployFilter.java:53)
                                at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter
                        .java:69)
                                at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
                                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Appl
                        icationFilterChain.java:235)
                                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationF
                        ilterChain.java:206)
                                at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFi
                        lter.java:96)
                                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(Appl
                        icationFilterChain.java:235)
                                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationF
                        ilterChain.java:206)
                                at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperV
                        alve.java:230)
                                at org.apache.catalina.core.StandardContextValve.invoke(StandardContextV
                        alve.java:175)
                                at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(Securit
                        yAssociationValve.java:182)
                                at org.apache.catalina.authenticator.AuthenticatorBase.invoke(Authentica
                        torBase.java:432)
                                at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValv
                        e.java:84)
                                at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.j
                        ava:127)
                                at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.j
                        ava:102)
                                at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedC
                        onnectionValve.java:157)
                                at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineVal
                        ve.java:109)
                                at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.jav
                        a:262)
                                at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java
                        :844)
                                at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.proce
                        ss(Http11Protocol.java:583)
                                at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:44
                        6)
                                at java.lang.Thread.run(Thread.java:619)
                        



                        seamServletAdapter is



                        public class SeamServletAdapter extends HttpServlet {
                                  private static final long serialVersionUID=8830027561411226041L;
                        
                                  @Override
                                  protected void service(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {
                                       String componentName=request.getParameter("component");
                                       System.out.println("SeamServletAdapter:componentName->"+componentName);
                                       if(componentName==null) {
                                            System.out.println("SeamServletAdapter:componentName is null ->"+componentName);
                                            String path=request.getRequestURI();
                                            int index=path.lastIndexOf('/');
                                            if(index>=0)
                                                 componentName=path.substring(index+1);
                                            if(componentName.endsWith(".seam"))
                                                 componentName=componentName.substring(0,componentName.length()-".seam".length());
                                       }
                                       try {
                                            System.out.println("SeamServletAdapter:before delegateToSeamComponent");
                                            delegateToSeamComponent(request,response,componentName);
                                       }
                                       catch(Exception e) {
                                            if(IOException.class.isAssignableFrom(e.getClass()))
                                                 throw (IOException)e;
                                            if(ServletException.class.isAssignableFrom(e.getClass()))
                                                 throw (ServletException)e;
                                            throw new ServletException("could not call Seam component "+componentName,e);
                                       }
                                  }
                        
                                  private void delegateToSeamComponent(HttpServletRequest request,HttpServletResponse response,String componentName)
                                            throws NoSuchMethodException,IllegalAccessException,InvocationTargetException {
                                       System.out.println("SeamServletAdapter:delegateToSeamComponent()");
                                       Object component=Component.getInstance(componentName);
                                       System.out.println("SeamServletAdapter:delegateToSeamComponent():component"+component);
                                       Method method=component.getClass().getMethod("service",HttpServletRequest.class,HttpServletResponse.class);
                                       method.invoke(component,request,response);
                                       System.out.println("SeamServletAdapter:delegateToSeamComponent():method.invoke");
                                  }
                        
                             }
                        
                        






                        web.xml is


                        
                        <?xml version="1.0" ?>
                        <web-app xmlns="http://java.sun.com/xml/ns/javaee"
                                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
                                 version="2.5">
                        
                            <!-- Ajax4jsf -->
                            
                            <context-param>
                                <param-name>org.richfaces.SKIN</param-name>
                                <param-value>classic</param-value>
                            </context-param>
                         
                           <!-- Seam -->
                            
                           <listener>
                              <listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
                           </listener>
                            
                            <filter>
                                <filter-name>Seam Filter</filter-name>
                                <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
                            </filter>
                        
                            <filter-mapping>
                                <filter-name>Seam Filter</filter-name>
                                <url-pattern>/*</url-pattern>
                            </filter-mapping>
                                
                           <servlet>
                              <servlet-name>Seam Resource Servlet</servlet-name>
                              <servlet-class>org.jboss.seam.servlet.SeamResourceServlet</servlet-class>
                           </servlet>
                            
                           <servlet-mapping>
                              <servlet-name>Seam Resource Servlet</servlet-name>
                              <url-pattern>/seam/resource/*</url-pattern>
                           </servlet-mapping>
                           
                           <!-- Facelets development mode (disable in production) -->
                           
                           <context-param>
                              <param-name>facelets.DEVELOPMENT</param-name>
                              <param-value>true</param-value>
                           </context-param>
                            
                           <!-- JSF -->
                           
                           <context-param>
                              <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
                              <param-value>.xhtml</param-value>
                           </context-param>
                        
                           <servlet>
                              <servlet-name>Faces Servlet</servlet-name>
                              <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
                              <load-on-startup>1</load-on-startup>
                           </servlet>
                            
                           <servlet-mapping>
                              <servlet-name>Faces Servlet</servlet-name>
                              <url-pattern>*.seam</url-pattern>
                           </servlet-mapping>
                           
                           <servlet>
                                  <servlet-name>Direct Seam Servlet</servlet-name>
                                  <servlet-class>mypack.SeamServletAdapter</servlet-class>
                           </servlet>
                        
                             
                             <servlet-mapping>
                                  <servlet-name>Direct Seam Servlet</servlet-name>
                                  <url-pattern>/seam/servlet/*</url-pattern>
                             </servlet-mapping>
                        
                           
                                          
                           <security-constraint> 
                               <display-name>Restrict raw XHTML Documents</display-name>
                               <web-resource-collection>
                                   <web-resource-name>XHTML</web-resource-name>
                                   <url-pattern>*.xhtml</url-pattern>
                               </web-resource-collection>
                               <auth-constraint/>
                           </security-constraint>
                           
                           
                           
                        </web-app>
                        
                        




                        component.xml is.


                        
                        
                        <?xml version="1.0" encoding="UTF-8"?>
                        <components xmlns="http://jboss.com/products/seam/components"
                             xmlns:core="http://jboss.com/products/seam/core" xmlns:persistence="http://jboss.com/products/seam/persistence"
                             xmlns:drools="http://jboss.com/products/seam/drools" xmlns:bpm="http://jboss.com/products/seam/bpm"
                             xmlns:security="http://jboss.com/products/seam/security" xmlns:mail="http://jboss.com/products/seam/mail"
                             xmlns:framework="http://jboss.com/products/seam/framework" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                             xmlns:web="http://jboss.com/products/seam/web"
                             xsi:schemaLocation="http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.0.xsd 
                                         http://jboss.com/products/seam/persistence http://jboss.com/products/seam/persistence-2.0.xsd 
                                         http://jboss.com/products/seam/drools http://jboss.com/products/seam/drools-2.0.xsd
                                         http://jboss.com/products/seam/bpm http://jboss.com/products/seam/bpm-2.0.xsd
                                         http://jboss.com/products/seam/security http://jboss.com/products/seam/security-2.0.xsd
                                         http://jboss.com/products/seam/framework http://jboss.com/products/seam/framework-2.0.xsd
                                         http://jboss.com/products/seam/mail http://jboss.com/products/seam/mail-2.0.xsd
                                         http://jboss.com/products/seam/components xmlns:web=http://jboss.com/products/seam/web http://jboss.com/products/seam/components-2.0.xsd">
                        
                             <core:init debug="true" jndi-pattern="@jndiPattern@" />
                        
                             <core:manager concurrent-request-timeout="500"
                                  conversation-timeout="120000" conversation-id-parameter="cid"
                                  parent-conversation-id-parameter="pid" />
                        
                             
                        
                             <persistence:managed-persistence-context
                                  name="entityManager" auto-create="true" persistence-unit-jndi-name="java:/posSeamEntityManagerFactory" />
                             <!--
                                  <drools:rule-base name="securityRules"> <drools:rule-files>
                                  <value>/security.drl</value> </drools:rule-files> </drools:rule-base>
                                  execute="#{redirect.returnToCapturedView}" /> </event>
                             -->
                             <event type="org.jboss.seam.security.notLoggedIn">
                                  <action execute="#{redirect.captureCurrentView}" />
                             </event>
                             <event type="org.jboss.seam.security.loginSuccessful">
                                  <action execute="#{redirect.returnToCapturedView}" />
                             </event>
                        
                        
                        
                             <mail:mail-session host="localhost" port="2525"
                                  username="test" password="test" />
                        
                             <security:identity authenticate-method="#{auth.authenticate}" />
                        
                             <!-- For use with jBPM pageflow or process management -->
                        
                             
                             
                             <!-- enable Seam for this non-JSF URL pattern -->
                           <web:context-filter url-pattern="/seam/servlet/*"/>
                             
                        
                        </components>
                        
                        
                        
                        



                        PrintSomething component is


                        @Name("printSomething")
                        public class PrintSomething extends HttpServlet{
                             
                             @In
                             private EntityManager entityManager;
                             
                             public void service(HttpServletRequest request,HttpServletResponse response) throws IOException,
                                       ServletException {
                                  File reportFile = null;
                                  reportFile = new File(request.getSession().getServletContext().getRealPath("/Reports/PurchaseOrder.jasper"));
                                  System.out.println("PrintSomething:service() After Getting Report File 1");
                                  
                                  File tmpFile = null;
                                  String fileName ="";
                                  
                                  try {
                                  
                                  JasperReport jasperReport = (JasperReport)JRLoader.loadObject(reportFile.getPath()); //reportFile.getPath()
                                       System.out.println("PrintSomething:service() After Getting Report File 2");
                                  
                                  Map<String, Object> params=new HashMap<String, Object>();
                                  convertRequestParameters(jasperReport,request.getParameterMap(),params);
                                  params.put("SUBREPORT_DIR","reports/");
                                  //params.put(JRJpaQueryExecuterFactory.PARAMETER_JPA_ENTITY_MANAGER,entityManager);
                                       System.out.println("PrintSomething:service() After Params Put");
                                  JasperPrint jasperPrint=JasperFillManager.fillReport(jasperReport,params);
                                  response.setContentType("application/pdf");
                                       System.out.println("PrintSomething:service() Contenttype set");
                                  java.io.OutputStream out=response.getOutputStream();
                                       System.out.println("PrintSomething:service()response.getOutputStream()");
                                  JRPdfExporter exporter=new JRPdfExporter();
                                       System.out.println("PrintSomething:service():exporter created");
                                  exporter.setParameter(JRExporterParameter.JASPER_PRINT,jasperPrint);
                                  exporter.setParameter(JRExporterParameter.OUTPUT_STREAM,out);
                                       System.out.println("PrintSomething:service() exporter.setParameter Done");
                                  exporter.exportReport();
                                       System.out.println("PrintSomething:service() exporter.exportReport()");
                                  }
                             
                                  catch (Exception e) {
                                       System.out.println("Stack Trace -> "+e.getStackTrace());
                                       System.out.println("Message -> "+e.getMessage());
                                       System.out.println("Cause -> "+e.getCause());
                                       
                                  }
                                  finally {
                                       //out.close();
                                  }
                             }
                             
                             public static void convertRequestParameters(JasperReport jasperReport,Map<String, String[]> requestParameterMap,
                                       Map<String, Object> jrParameterMap) {
                                  JRParameter[] params=jasperReport.getParameters();
                                  System.out.println("PrintSomething:convertRequestParameters()1");
                                  for(JRParameter p : params) {
                                       System.out.println("PrintSomething:convertRequestParameters() inside For");
                                       String[] values=requestParameterMap.get(p.getName());
                                       if(values==null||values.length==0) continue; // parameter not provided
                                       Object o;
                                       if(!p.getValueClass().equals(String.class)) // convert string to desired type
                                            o=ConvertUtils.convert(values[0],p.getValueClass());
                                       else o=values[0]; // String is expected and we have string, should be ok
                                       jrParameterMap.put(p.getName(),o);
                                  }
                             }
                        
                        
                        }
                        
                        



                        Do i missing some configuration that needs to be done.
                        Please help me on this.


                        Thanks.






                        • 9. Re: JasperReports + Seam
                          cleiton alan  schultz herrmann Newbie
                          Hi.

                          I don't known where I have to put the jasper files (report.jrxml). I've tried to put it into "WEB-INF/reports" at the .war file that is into the .ear file, but when I use the code below to get an Inputstream of the report, the input stream returned is null.
                          ServletContext servletContext = (ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext();
                          String path = servletContext.getRealPath("WEB-INF/reports/").replace("./", "");
                          String file = "/report.jrxml";
                          InputStream reportTemplate = this.getClass().getClassLoader().getResourceAsStream("RelatorioTeste.jrxml");

                          The path + file string is
                          /home/cleitonash/java/jboss-4.2.3.GA/server/default/tmp/deploy/tmp7470986768939011299jboss-seam-itext.ear-contents/jboss-seam-itext-exp.war/WEB-INF/reports/report.jrxml

                          What I'm doing wrong ?
                          Thanks...

                          • 11. Re: JasperReports + Seam
                            Jubril Adisa Novice

                            I followed the suggestions but i am getting



                            com.sun.jdi.InvocationException occurred invoking method.
                            
                            12:33:53,588 ERROR [[Direct Seam Servlet]] Servlet.service() for servlet Direct Seam Servlet threw exception
                            java.lang.IllegalStateException: No active event context
                                 at org.jboss.seam.core.Manager.instance(Manager.java:368)
                                 at org.jboss.seam.servlet.ContextualHttpServletRequest.run(ContextualHttpServletRequest.java:55)
                                 at org.jboss.seam.web.ContextFilter.doFilter(ContextFilter.java:37)
                                 at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                 at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:178)
                                 at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290)
                                 at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.jav