среда, 12 ноября 2008 г.

GWT (GWT-EXT) + JasperReports быстро и просто.

Часть первая, как все началось
Вы энтузиаст новых инновационных технологий, разрабатываете корпоративное решение на Google Web Toolkit (GWT), но вот однажды в третьем часу ночи из бани звонит вам клиент, и сообщает,что зайдет днем пообщаться насчет работы с отчетами.
Какие еще отчеты, вон какие симпатичные панельки, окошки, кнопочки думаете вы. Но вспомнив, что клиенто-ориентированность это хорошо, решаем ввести клиента в восторг.

Начнем, как водится, с постановки задачи.
Постановка задачи
Задача у нас не очень сложная, но вместе с тем не совсем тривиальная – создать прототип запуска, просмотра отчетов, а также уметь экспортировать в различные форматы.
Вам понадобится

Чтобы собрать приложение своими руками, вам понадобятся следующие инструменты:
  1. Gwt (Gwt-Ext) приложение :)
Немного о JasperReports

JasperReports один из популярных Open Source библиотек для создания отчетов. Очень просто интегрируется в любые Java аппликации.

Отчеты описываются в формате XML, что в последующем возможно создание отчетов на базе шаблонов, использую Velocity (http://velocity.apache.org/), Jelly (http://commons.apache.org/jelly/) или другие инструментарии. Файлы имеют расширение *.jrxml.

Далее файл отчета компилируется, и на выходе получаем файлы *.jasper.


JasperCompileManager.compileReportToFile("WebappReport.jrxml");

В некоторых случаях это удобно, так как дает возможность в эксплуатации поставлять клиентам готовый отчет, а не исходники его.


После этого отчет запускается с помощью JasperFillManager.fillReport() в результате получаем JasperPrint объект, также возможно сохранить в файл.


В конце используя один из классов JexcelApiExporter, JexcelApiExporterNature, JexcelApiExporterParameter, JRCsvExporter, JRGraphics2Dexporter, JRHtmlExporter, JRPdfExporter, JRPrintServiceExporter, JRRtfExporter, JRTextExporter, JRXlsExporter, JRXmlExporter можем экспортировать отчет в любой из данных форматов.


Прототип приложения


Для примера взят протип приложения GWT-Ext Showcase2, переделанный в рамках требований клиента.



Когда мы кликаем “Logined users”, информация разворачивается в новом табе, показывая детали. Пока все просто и ясно? Теперь все по порядку.

Первый шаг


Итак, перво-наперво поработаем с Jasper и создадим сам отчет

  • Имеем jasperreports-3.1.2-project.zip, разархивируем его в C:\demo\jasper. Находим в директории “demo\samples\webapp” (отличный пример для запуска отчетов под web) отчет WebappReport.jrxml

  • Далее используя iReport подправляем отчет под наши нужды, заменяем заголовок отчета, а также настраиваем JDBC DataSource и Report Query.



  • Слегка меняем исходники в директории “demo\samples\webapp\WEB-INF\classes\servlets” – делаем возможность запуска отчета используя параметр reportfile: String rp = req.getParameter(“reportfile”); String reportFileName = context.getRealPath("/reports/”+rp+”.jasper");
    “demo\samples\webapp” для тестирования – в HTML все линки прописываем название отчета “?reportfile=WebappReport”;

  • В корневом каталоге “ demo\samples\webapp” запускаем ANT.


Итак, после настройки Tomcat, копируем содежимое “demo\samples\webapp” в Tomcat ”webapps\jasper”, и запускаем его.


Открываем браузер вводим туда ссылку ниже (Внимание у вас может отличаться порт!).
http://localhost:8887/jasper/


Здесь же и проверяем отчет.

Второй шаг

Итак, отчет у нас работает, теперь приступаем к GWT. При нажатии на “Logined users”, открывается пустой таб:



Осталось интегрировать Jasper.

Создаем простейший ReportManager class со статическим методом:
public class ReportManager {
public static String getExportReportURL(String report, String exptype){
return "http://localhost:8887/jasper/servlets/"+exptype+"?reportfile=" + report;
};

}

Далее создаем панель:

Panel centerPanel = new Panel();
centerPanel.setLayout(new BorderLayout());
centerPanel.setTitle("Sessions");


String rep_url = ReportManager.getExportReportURL("WebappReport","html");
final Frame frame = new Frame(rep_url);
centerPanel.add(frame, new BorderLayoutData(RegionPosition.CENTER));

Toolbar toolbar = new Toolbar();
toolbar.addFill();
ToolbarButton toolbarButton = new ToolbarButton("PDF", new ButtonListenerAdapter() {
public void onClick(Button button, EventObject e) {
frame.setUrl(ReportManager.getExportReportURL("WebappReport","pdf"));
}
});


Запускаем проект в Host Mode, нажимаем на “Logined users” и .... получаем

При нажатии PDF – мы увидим отчет уже в Pdf формате:


Теперь осталось дождаться клиента и за чашечкой кофе рассказать о будущих перспективах :)

четверг, 6 ноября 2008 г.

Как сделать GWT StackPanel пοхожим на Outlook

На этот раз хочется поделиться новым компонентом на GWT - Outlook Stack Panel.
Почему я решил написать его?
Проблема в том, что стандартный StackPanel от GWT, работает так, что при выборе закладки, она сдвигает другие закладки и показывается ее содержание. При этом получается так, что содержание закладки все время скочет вверх и вниз, что на мой взгляд не очень user friendly.

Пример stack панели, как бы я ее хотел видеть - Outlook stack panel: содержимое всегда находится в одном месте, кнопки не скочат и имеют один и тот же порядок.
Вот что у меня получилось.




Как видете, при смене закладки сами закладки остаются на том же месте, меняется заголовок и содержание.
Реализуется это используя DeckPanel компонент.


/**
* Creates an empty stack panel.
*/
public OutlookStackPanel() {
content.setAnimationEnabled(true);
content.setWidth(DEFAULT_WIDTH);

container.setStyleName(DEFAULT_STYLE);
header.setSize(DEFAULT_WIDTH, DEFAULT_HEADER_HIGHT);
footer.setSize(DEFAULT_WIDTH, "");

ScrollPanel scroller = new ScrollPanel();
scroller.setAlwaysShowScrollBars(false);
scroller.add(content);

container.setVerticalAlignment(HasVerticalAlignment.ALIGN_TOP);
container.add(header);
container.add(scroller);

container.setVerticalAlignment(HasVerticalAlignment.ALIGN_BOTTOM);
container.add(footer);

content.setAnimationEnabled(true);

header.setStyleName(DEFAULT_HEADER_STYLE);

initWidget(container);

sinkEvents(Event.ONCLICK);
sinkEvents(Event.ONMOUSEOVER);
sinkEvents(Event.ONMOUSEOUT);
}


Затем не хитрый код, для отображениа нужного содержания

@Override
public void onBrowserEvent(Event event) {

Element target = event.getTarget();
if (DOM.eventGetType(event) == Event.ONCLICK) {
for (Widget widget : buttons) {
if (widget.getElement() == target) {
buttons.get(header.getVisibleWidget()).removeStyleDependentName("selected");
widget.addStyleDependentName("selected");

int index = buttons.indexOf(widget);
if (index >= 0) {
header.showWidget(index);
content.showWidget(index);
}
}
}
} else if (DOM.eventGetType(event) == Event.ONMOUSEOVER) {
...
...
} else if (DOM.eventGetType(event) == Event.ONMOUSEOUT) {
...
...
}


Вы можете скачать исходники здеся ;) Удачи!
В скором времени, я надеюсь выложить GWT application starter here (gwtfuse):

Если кто либо сделал это более красиво и элегантно, то прошу поделиться идеями ;)

суббота, 1 ноября 2008 г.

Как сделать красивую кнопку в GWT

GWT прекрасный инструмент для разработки веб апликаций. На мой взгляд, единственный недостаток его на сегодняшний день - недостаток красивых компонентов. Конечно, это легко решить с помощью Gwt-ext или Ext-gwt, но, хотите ли вы добавлять на ваш сайт всю библиотеку этих скриптов и становиться зависимым от них? А что если вам нужно всего навсего несколько компонентов?
Недавно, работая в одном GWT проекте нам понадобилось создать кнопки определенного вида и я решил, почему бы не поделиться этим с другими любителями GWT.



Так может выглядеть кнопка. Используя CSS и GWT Hyperlink, можно создать кнопку любого вида.
Я не нашел, как можно поместить рабочий пример на сайт, и поместил линк, по которому можно скачать скомпилированный пример (если вам лень настраивать проект в Eclipse): Скомпилированная версия, а также вы можете скачать исходники по этой ссылке: Скачать исходники

Если у вас есть лучше идеи, как сделать эти кнопки, пишите, буду рад!