Thursday, July 14, 2011

Emissão de relatórios no Spring Roo e MVC com Jasper Reports

O Spring MVC é uma das tecnologias que mais gostamos e usamos na YaW. Quando uso o termo "gostar" na verdade me refiro a uma tecnologia que atendeu as nossas espectativas do ponto de vista de implementação e mais importante, supriu as necessidades e objetivos do nosso cliente. A nossa experiência com Spring MVC tem sido bem interessante, por isso faz parte de nosso portfólio de soluções.

Nesse post demonstro como intregrar uma aplicação Web desenvolvida pelo Spring MVC com o JasperReports para emissão de relatórios. A integração entre o Spring MVC e JasperReports não tem nenhuma relação com o Spring Roo, mas para facilitar a criação e o desenvolvimento do projeto vou assumir o uso do Spring Roo.

Dependências

Além da biblioteca do JasperReports, dependendo do caso precisamos de outras libs complementares:
  • Spring Support
  • iText (pdf)
  • POI  (xls)


A seguir o trecho do pom.xml (Maven) com configuração dos artefatos. No trecho abaixo também coloco as configurações para o plugin do Maven que automatiza a compilcação dos relatórios jrxml para o formato jasper, utilizado pelo JasperReports:

...
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context-support</artifactId>
  <version>${spring.version}</version>
</dependency>
<dependency>
  <groupId>net.sf.jasperreports</groupId>
  <artifactId>jasperreports</artifactId>
  <version>4.0.0</version>
</dependency>
<dependency>
  <groupId>com.lowagie</groupId>
  <artifactId>itext</artifactId>
  <version>2.1.7</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi</artifactId>
  <version>3.6</version>
  <scope>compile</scope>
  <optional>true</optional>
</dependency>
...
<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>jasperreports-maven-plugin</artifactId>
  <configuration>
    <sourceDirectory>src/main/webapp/WEB-INF/reports</sourceDirectory>
    <outputDirectory>src/main/webapp/WEB-INF/reports</outputDirectory>
  </configuration>
  <executions>
    <execution>
      <goals>
        <goal>compile-reports</goal>
      </goals>
    </execution>
  </executions>
  <dependencies>
    <dependency>
      <groupId>jasperreports</groupId>
      <artifactId>jasperreports</artifactId>
      <version>3.5.3</version>
    </dependency>
    <dependency>
      <groupId>org.apache.log4j</groupId>
      <artifactId>com.springsource.org.apache.log4j</artifactId>
      <version>1.2.15</version>
    </dependency>
  </dependencies>
</plugin>
...

Próxima etapa é configurar no xml do MVC (webmvc-config.xml) o viewResolver do Spring que indica o properties com as configurações de cada relatório.

<bean id="viewResolver" 
  class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
  <property name="basename" value="relatorios"/>
</bean>

O arquivo relatorios.properties (na raiz do diretório de classes) armazena qual a classe que estipula o formato de geração do relatório, a url com o caminho do arquivo do relatório.

No exemplo estou usando o arquivo compilado, o .jasper, mas o Spring aceita a extensão jrxml. A propriedade reportKeyData (opcional) indica o apelido para o DataSource com os dados que o relatório depende. Já o valor relatorioPedidos usado como base das 3 chaves é o identificador do relatório, usamos no retorno do método da Controller que processa o relatório.

relatorioPedidos.(class)=
org.springframework.web.servlet.view.jasperreports.JasperReportsMultiFormatView
relatorioPedidos.url=/WEB-INF/reports/pedidos.jasper
relatorioPedidos.reportDataKey=pedidosDS

A classe JasperReportsMultiFormatView é indicada em relatórios que podem ser emitidos em mais de um formato, ou seja, o mesmo relatório gerado em xls e pdf. Outra alternativa seria utilizar JasperReportsPdfView, nesse caso a emissão ocorre só em pdf.

Pra fechar o método da Controller que processa os dados para emissão do relatório:

...
@RequestMapping("/report")
@Controller
public class ReportController {

  @RequestMapping(value ="/pedido/pdf", method = RequestMethod.GET)
  public String processaRelatorioPedidos(
     @RequestParam String de, @RequestParam String ate,
     ModelMap modelMap) 
  {
    JRBeanCollectionDataSource ds =
      new JRBeanCollectionDataSource(Pedido.findPedidosByDataGeracao(de, ate),false);
    modelMap.put("pedidosDS", ds);
    return "relatorioPedidos";
  }

}

A documentação oficial do Spring disponibiliza um capítulo sobre a integração do Spring MVC com o JasperReports.

@edermag
www.yaw.com.br

1 comment:

Andre Wirth said...

gostei do exemplo, trabalhei um pouco com o ROO, vou tentar implementar algum relatório agora