Статьи

JasperReports JSF Плагин Сценарии использования

Это отправная точка серии статей, в которой я попытаюсь охватить некоторые варианты использования JSperReport JSF Plugin , инструмента, созданного для простой интеграции бизнес-отчетов, разработанных для JasperReports, в приложения JSF. Все примеры, описанные в этой серии, доступны на веб-сайте JSF Plugin JasperReports в разделе примеров и станут частью одного и того же бизнес-приложения: Интернет-магазина книг.

Серия будет проходить через шаги, необходимые для создания предыдущего упомянутого веб-приложения. Я постараюсь сделать статьи как можно более аккуратными, самодостаточными и законченными, но я намеренно опущу некоторые части, не связанные конкретно ни с одной из основных технологий, представленных здесь. Таким образом, каждая статья пойдет прямо к сути и будет менее многословной, что позволит легче понять главных действующих лиц и их роли.

Прежде чем углубляться в материал, в котором я объясню различные сценарии для JSF-плагина JasperReports, нам нужно настроить проект веб-приложения, который станет отправной точкой для дальнейших сценариев использования. Основные инструменты, используемые в этой серии для работы над этим проектом:

  • JasperReports 4.5.1: механизм отчетов.
  • iReport 4.5.1: дизайнер визуальных отчетов
  • Java Server Faces 1.2 и Facelets 1.1.1: веб-инфраструктура для моего приложения (обратите внимание, что это можно легко перенести в JSF 2.x).
  • JasperReports JSF Plugin 1.0: мост интеграции между механизмом отчетности и веб-фреймворком.
  • Apache Derby 10.8.2.2: база данных, которая будет содержать необходимую нам информацию.
  • Apache Tomcat 6.0.35: сервер приложений, который я буду использовать для развертывания и тестирования приложения.

Данные, которые будут отображаться в каждом конкретном отчете, будут поступать из простой базы данных с несколькими таблицами, которые будут содержать необходимую нам информацию. Основные сущности, которые я буду использовать для составления модели предметной области, в основном: книги , клиенты , заказы и строки заказа .

содержание

Настройка проекта

Подход, который я буду использовать, заключается в создании нового веб-проекта, который будет использовать эту модель базы данных. Я буду использовать Maven для настройки и управления зависимостями, которые я буду использовать, так как я к этому довольно привык, и я не буду самостоятельно собирать все файлы jar и настраивать их вручную в своей базе кода. Любой другой может использовать инструмент по своему усмотрению ( Ant , Gradle , на основе IDE и т. Д.).

Хороший пример для этого с Maven — образец архетипа «simple-webapp» из Maven Book . Я опубликую здесь предложение командной строки, которое я использовал для создания структуры моего проекта с использованием этого архетипа:

1
2
3
4
5
6
7
mvn archetype:create -DgroupId=net.sf.jasperreports.jsf.sample
-DartifactId=jrjsf-usecases
-Dpackage=net.sf.jasperreports.jsf.sample.usecases
-Dversion=1.0-SNAPSHOT
-DarchetypeArtifactId=maven-archetype-webapp
-DarchetypeGroupId=org.apache.maven.archetypes
-DarchetypeVersion=1.0

Это создаст проект Maven в папке с именем jrjsf-usecases и со следующими начальными значениями:

  • идентификатор группы : net.sf.jasperreports.jsf.sample
  • artifactId : jrjsf-usecases
  • версия : 1.0-SNAPSHOT
  • пакет : net.sf.jasperreports.jsf.sample.usecases

Теперь нужно немного изменить файл pom.xml, чтобы он содержал зависимости, необходимые для нашего проекта. Основные изменения, которые я сделаю, будут состоять в добавлении поддержки Java 1.5 (и выше) и зависимостей к элементам, перечисленным в начале статьи.

Чтобы иметь возможность использовать дженерики и другие необычные функции, добавленные в Java после выпуска Java 5, нам нужно настроить плагин maven-compiler-plugin, чтобы компилятор Java мог распознать, что нам нужна поддержка этих функций:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
<project>
    ...
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <groupId>org.apache.maven.plugins</groupId>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

А теперь давайте добавим зависимости, которые нам нужны для реализации нашего приложения:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<project>
    ...
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.4</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>el-api</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>javax.faces</groupId>
            <artifactId>jsf-api</artifactId>
            <version>1.2_14</version>
        </dependency>
        <dependency>
            <groupId>javax.faces</groupId>
            <artifactId>jsf-impl</artifactId>
            <version>1.2_14</version>
        </dependency>
        <dependency>
            <groupId>com.sun.facelets</groupId>
            <artifactId>jsf-facelets</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>net.sf.jasperreports</groupId>
            <artifactId>jasperreports</artifactId>
            <version>4.5.1</version>
        </dependency>
        <dependency>
            <groupId>net.sf.jasperreports.jsf</groupId>
            <artifactId>jasperreports-jsf</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.derby</groupId>
            <artifactId>derbyclient</artifactId>
            <version>10.8.2.2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

В этом проекте мы будем использовать управляемый контейнером источник данных, доступный через JNDI. Этот тип конфигурации зависит от типа сервера приложений, который мы используем. Поскольку я использую Tomcat в качестве сервера приложений, мне нужно добавить файл context.xml в наш проект в папке src / main / webapp / META-INF, чтобы сообщить ему, как получить доступ к этой базе данных и типу ресурса. Я хочу:

1
2
3
4
5
6
7
8
9
<Context path='/jrjsf-usecases' reloadable='true'>
 
 <Resource name='jdbc/BookStoreDB' auth='Container' type='javax.sql.DataSource'
  maxActive='100' maxIdle='30' maxWait='10000'
  username='app' password='' driverClassName='org.apache.derby.jdbc.ClientDriver'
  url='jdbc:derby://localhost:1527/bookstoredb;create=true'
 />
 
</Context>

Настройка iReport

Нам нужно настроить iReport, чтобы он мог подключаться к нашей базе данных, поэтому давайте запустим инструмент проектирования iReport и настроим его так, чтобы он был готов к работе по проектированию. iReport не предоставляет встроенной поддержки базы данных Apache Derby, нам нужно добавить библиотеки в ее путь к классам и вручную настроить драйвер JDBC Derby. Это упражнение научит нас настраивать инструмент для поддержки любой другой базы данных.

Прежде всего, загрузите базу данных Apache Derby со своего веб-сайта и установите ее (распакуйте zip-файл) в папку по вашему выбору на локальном компьютере, если вы еще этого не сделали. Затем откройте окно настроек / опций iReport и выберите вкладку classpath:

Я добавлю папку lib Derby в путь к классам iReport. Для этого нажмите кнопку «Добавить папку» и просматривайте файловую систему, пока не доберетесь до папки lib внутри установки Apache Derby:

После этого нажмите кнопку ОК в окне настроек, и теперь клиентские классы Apache Derby должны быть доступны в iReport. На данный момент мы готовы настроить источник данных Apache Derby в iReport, который будет использоваться нашими отчетами. Чтобы добавить новый источник данных, мы можем начать со страницы приветствия iReport и нажать кнопку « Шаг 1 : Создать соединение с базой данных…» или нажать кнопку «Сообщить об источниках данных» на панели инструментов, а затем нажать «Добавить». кнопка. В любом случае мы попадем в окно, подобное следующему:

Источник данных Apache Derby должен быть полностью настроен вручную в iReport, поэтому выберите «Соединение с базой данных JDBC» в списке из предыдущего окна, нажмите «Далее>» и введите значения для драйвера JDBC в следующем окне:

Значения для полей следующие:

  • Имя : BookStoreDB
  • Драйвер JDBC : org.apache.derby.jdbc.ClientDriver
  • URL JDBC : jdbc: derby: // localhost: 1527 / bookstoredb
  • Имя пользователя : приложение
  • Пароль : <пусто>

Теперь, прежде чем продолжить, убедитесь, что ваш экземпляр Apache Derby работает, чтобы разрешить соединения с ним, и нажмите кнопку «Тест», чтобы проверить, что все в порядке.

Модель предметной области

Допустим, наш проект настроен и готов начать работу над ним (у нас есть базовая структура папок проекта, и все основные зависимости находятся в нашем пути к классам, и iReport может подключаться к нашей базе данных), поэтому давайте начнем с небольшого код. Моим первым шагом в этой области будет создание файла SQL ( bookstore.create.sql ) для инициализации модели домена, о которой я говорил в параграфе «Введение» этой серии. Скопируйте текст под этим абзацем и вставьте его в файл внутри структуры папок вашего проекта, чтобы вы могли использовать его позже:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
create table book (
    book_id int generated by default as identity primary key,
    title varchar(50) not null,
    author varchar(50) not null,
    published_year varchar(4) not null,
    genre varchar(20) not null,
    price numeric not null
);
 
create table customer (
    customer_id int generated by default as identity primary key,
    name varchar(250) not null
);
 
create table purchase_order (
    order_id int generated by default as identity primary key,
    customer_id int not null,
    created_date date not null,
 
    constraint customer_fk foreign key (customer_id) references customer(customer_id)
);
 
create table purchase_order_line (
    order_line_id int generated by default as identity primary key,
    order_id int not null,
    book_id int not null,
    item_count int not null,
 
    constraint order_fk foreign key (order_id) references purchase_order(order_id),
    constraint book_fk foreign key (book_id) references book(book_id)
);

Это только бэкэнд-часть моей доменной модели, в моем приложении мне нужно также представлять эти объекты как классы Java. Итак, чтобы завершить эту модель предметной области, моим следующим шагом будет написать классы Java, которые мне нужны для представления предыдущей определенной модели предметной области внутри моего Java-приложения. Теперь пришло время взглянуть на предыдущую модель, у нас есть 4 различных объекта, поэтому нам потребуется 4 различных класса внутри нашего Java-приложения, чтобы соответствовать этой модели:

Книга

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public class Book {
 
    private Long id;
 
    private String title;
 
    private String author;
 
    private String publishedYear;
 
    private String genre;
 
    private double price;
 
    public String getAuthor() {
        return author;
    }
 
    public void setAuthor(String author) {
        this.author = author;
    }
 
    public String getGenre() {
        return genre;
    }
 
    public void setGenre(String genre) {
        this.genre = genre;
    }
 
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public double getPrice() {
        return price;
    }
 
    public void setPrice(double price) {
        this.price = price;
    }
 
    public String getPublishedYear() {
        return publishedYear;
    }
 
    public void setPublishedYear(String publishedYear) {
        this.publishedYear = publishedYear;
    }
 
    public String getTitle() {
        return title;
    }
 
    public void setTitle(String title) {
        this.title = title;
    }
 
}

Клиент

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Customer {
 
    private Long id;
 
    private String name;
 
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
}

порядок

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class Order {
 
    private Long id;
 
    private Customer customer;
 
    private Date createdDate;
 
    private List lines = new ArrayList();
 
    public Date getCreatedDate() {
        return createdDate;
    }
 
    public void setCreatedDate(Date createdDate) {
        this.createdDate = createdDate;
    }
 
    public Customer getCustomer() {
        return customer;
    }
 
    public void setCustomer(Customer customer) {
        this.customer = customer;
    }
 
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public List getLines() {
        return lines;
    }
 
    public void setLines(List lines) {
        this.lines = lines;
    }
 
}

OrderLine

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class OrderLine {
 
    private Long id;
 
    private Order order;
 
    private Book book;
 
    private int itemCount;
 
    public Book getBook() {
        return book;
    }
 
    public void setBook(Book book) {
        this.book = book;
    }
 
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public int getItemCount() {
        return itemCount;
    }
 
    public void setItemCount(int itemCount) {
        this.itemCount = itemCount;
    }
 
    public Order getOrder() {
        return order;
    }
 
    public void setOrder(Order order) {
        this.order = order;
    }
 
}

Теперь используйте инструмент по вашему выбору для подключения к вашей базе данных и выполните файл bookstoredb.create.sql, чтобы создать структуру таблицы.

Вывод

Я стараюсь сделать код максимально простым и чистым. Классы Java, перечисленные в предыдущем разделе, могут быть сопоставлены с нашей реляционной базой данных с помощью инструментов ORM, таких как Hibernate , iBATIS , Ebean и т. Д. Я оставляю выбор слоя Object Relational Mapping читателю, так как вариантов много, и ни один из них повлияет на то, как мы интегрируем наш отчет с веб-фреймворком.

Наше веб-приложение должно содержать другие классы для составления его архитектуры в виде DAO и бизнес-фасадов и контроллеров представления. Однако добавление всех из них в этой статье полностью выходит за рамки той же причины, по которой я не добавляю информацию ORM, которая может помочь связать классы модели с таблицами базы данных. В настоящее время существует множество IoC-контейнеров ( Spring Framework , Weld , Seam и т. Д.), И что действительно важно в этой серии, так это продемонстрировать использование JSF-плагина JasperReports. (Контроллеры представлений будут перечислены в отдельной статье, поскольку они являются частью каждого конкретного варианта использования).

И это все, что нам нужно, чтобы начать работать с различными примерами этого изящного инструмента. В течение следующих недель будут опубликованы новые статьи в категории JSF Plugin JasperReports, в которых будут приведены подробные примеры, демонстрирующие, как реализовать наиболее распространенные варианты использования. Надеюсь, вам понравится, любые комментарии приветствуются.

Ссылка: JasperReports JSF Plugin Use Cases Series от нашего партнера JCG Алонсо Домингеса в блоге Code Nibbles .