Совсем недавно начал изучать Grails до этого был опыт работы с Groovy. Язык понравился.
5 февраля(позавчера) вышла в свет первая версия фреймворка.
Хочу узнать мнение разработчиков работавших или работающих с данным фреймворком.
Интересуют надежность, удобство использования, быстрота разработки, интеграция с Flex, GWT...
Re: Grails
От:
Аноним
Дата:
07.02.08 13:47
Оценка:
С лета прошлого года использую grails для написания проекта.
Опыт программирования в java не имел, переходил с PHP.
Могу отметить, что довольно быстро получается.
Интеграция с GWT есть в виде плагина. Сам его использую, доволен. Есть некоторые неудобства если надо прицепить дополнительную библиотеку типа gwt-ext или mygwt, проблема решилась редактированием скриптов плагина.
Очень удобно работать с grails из idea. Не идеально конечно, но каждую неделю плагин становиться лучше.
Flex тоже есть в виде плагина. Но работать с ним не довелось.
К сожалению проект еще не вышел на стадию опытной эксплуатации, поэтому ни чего не могу сказать про скорость, надежность и другие показатели
Здравствуйте, Аноним, Вы писали:
А>С лета прошлого года использую grails для написания проекта. А>Опыт программирования в java не имел, переходил с PHP. А>Могу отметить, что довольно быстро получается.
А>Интеграция с GWT есть в виде плагина. Сам его использую, доволен. Есть некоторые неудобства если надо прицепить дополнительную библиотеку типа gwt-ext или mygwt, проблема решилась редактированием скриптов плагина.
Я тоже использую gwt-ext. Интересно, а много кода нужно переписывать?
Единственное неудобство это то, что еще в ${project}/lib надо положить gwtext.jar.
Так как после того как gwt плагин компилирует. Эти же классы обычным компилятор тоже цепляются (javac).
Во время разработки это не сильно мешает, но когда получишь war надо будет их удалить, чтобы место не занимали и gwtext.jar удалить из него.
Разработчик обещал этот и еще некоторые глюки исправить.
Вообще в новой версии он сильно облегчил подключение сторонних расширения для gwt.
Раньше надо было 3 файла править
Здравствуйте, BAKAB, Вы писали:
M>>Я тоже использую gwt-ext. Интересно, а много кода нужно переписывать?
BAK>Нет одну строчку добавить. BAK>${project}/plugins/gwt-0.2.3/scripts/_Internal.groovy
BAK>Ищешь в target (compileGwtModules: "Compiles any GWT modules in 'src/java'.") строчку
BAK>
BAK>Единственное неудобство это то, что еще в ${project}/lib надо положить gwtext.jar. BAK>Так как после того как gwt плагин компилирует. Эти же классы обычным компилятор тоже цепляются (javac). BAK>Во время разработки это не сильно мешает, но когда получишь war надо будет их удалить, чтобы место не занимали и gwtext.jar удалить из него. BAK>Разработчик обещал этот и еще некоторые глюки исправить.
BAK>Вообще в новой версии он сильно облегчил подключение сторонних расширения для gwt. BAK>Раньше надо было 3 файла править
Что-то у меня не получается. Все компилируется без ошибок, но на самой странице $wnd.Ext has no properties
Использую Идею, grails 1.0.1, gwt плагин через grails install-plugun. _Internal.groovy поправил.
Если не трудно, собери пустой проект (какую-нибудь кнопку выведи) и выложи архивом где-нибудь.
Или сравним:
nb — корень
\lib — gwtext.jar
...
\plugins\gwt-0.2.4\ ...
сейчас выглядит так
...
echo(message: "Module: ${moduleName}")
java(classname: 'com.google.gwt.dev.GWTCompiler', fork: 'true') {
// Have to prefix this with 'Ant' because the Init
// script includes a 'classpath' target.
Ant.classpath {
fileset(dir: "${gwtHome}") {
include(name: 'gwt-dev*.jar')
include(name: 'gwt-user.jar')
}
fileset(dir: "${basedir}/lib") {
include(name: 'gwtext.jar')
}
pathElement(location: "${basedir}/${srcDir}")
pathElement(location: "${basedir}/lib/gwtext.jar")
}
arg(value: '-out')
arg(value: outputPath)
arg(value: moduleName)
}
...
\src\java\test\client\test.java подобрал пример попроще из demo
package test.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.gwtext.client.widgets.ColorPalette;
import com.gwtext.client.widgets.Panel;
import com.gwtext.client.widgets.Viewport;
import com.gwtext.client.widgets.event.ColorPaletteListenerAdapter;
import com.gwtext.client.widgets.form.TextField;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class TestGWT implements EntryPoint {
/**
* This is the entry point method.
*/
public void onModuleLoad() {
Panel panel = new Panel();
panel.setBorder(false);
panel.setPaddings(15);
VerticalPanel verticalPanel = new VerticalPanel();
verticalPanel.setSpacing(15);
final TextField textField = new TextField("Color");
textField.setWidth(146);
ColorPalette colorPalette = new ColorPalette();
colorPalette.addListener(new ColorPaletteListenerAdapter() {
public void onSelect(ColorPalette colorPalette, String color) {
textField.setStyle("background-color:" + color + ";background-image:none;");
textField.setValue(color);
}
});
colorPalette.setTitle("Pick a color");
verticalPanel.add(colorPalette);
verticalPanel.add(textField);
panel.add(verticalPanel);
RootPanel.get().add(panel);
}
\web-app\gwt\ тут все что после gwt компилятора получется
Здравствуйте, unreger, Вы писали:
U>Что-то у меня не получается. Все компилируется без ошибок, но на самой странице $wnd.Ext has no properties U>Использую Идею, grails 1.0.1, gwt плагин через grails install-plugun. _Internal.groovy поправил.
В версии плагина gwt-0.2.4 не надо уже править файл _Internal.groovy надо просто в {project}/lib/gwt положить библиотеку.
Ошибка $wnd.Ext has no properties может возникать в том случае если на странице (gsp, jsp, html) нет загрузки ext библиотек.
Соответсвено ext библиотеку надо тоже загрузить и разместить в проекте. Я для себя выбрал каталог {project}/js/ext
U>Если не трудно, собери пустой проект (какую-нибудь кнопку выведи) и выложи архивом где-нибудь.
Сейчас времени нет. Может в выходные соберу пустой проект с примером для IDEA
U>компилирую как grails application
Про grails application ни чего не нашел! Может у меня задачи другие
Я компилирую как grails run-app так как файлы в проекте разложены не так как рекомендует google.
Надеюсь смог помочь, если нет пиши, будет стимул собрать пустой проект
За неделю слегка поразбирался с контролами.
Но теперь не совсем понятно как совмещаются controller от grails и java-класс от gwt-ext для страницы.
Вот grails:
доменный класс
контроллер к нему
за view часть теперь отвечает gwt-ext
пойдем с другой стороны:
gsp страница (практически пустая — только подключаются библиотеки, будет формироваться динамически)
java-класс к этой странице
ээээ.... а теперь как?
Что и где размещать?
Вот пусть будет
class Test {
String testValue
}
class TestController {
def view() { //-видимо нужна функция а не action?
[test: Test.list()]
}
}
Как теперь вывести список на страницу? В случае чистого grails я бы воспользовался gsp тегом, но сейчас страница динамически строится по java коду. Допустим, из java класса я вызову функцию из контроллера, получу список, потом начну по нему идти, формируя новый список уже как gwt-ext объект. Как-то это неправильно. И как быть с action? И вообще, есть ли смысл в grails-контроллере?
Ну и вопрос на будущее — а если я захочу добавить еще и ajax обновление, то как-то надо разместить <div> теги. Видимо через setHtml?
Но тогда все что дальше внутри тега — руками формировать html? (Например, список, который обновляется через ajax)
Здравствуйте, unreger, Вы писали:
U>За неделю слегка поразбирался с контролами. U>Но теперь не совсем понятно как совмещаются controller от grails и java-класс от gwt-ext для страницы.
Тот же этот вопрос меня мучает.
В своем проекте использую контроллер только для того, чтобы определить какое gwt приложение показывать.
Передачу параметров в gwt-приложение осуществляю через json объекты или ajax (GWT-RPC)
Здравствуйте, BAKAB, Вы писали:
BAK>Здравствуйте, unreger, Вы писали:
U>>За неделю слегка поразбирался с контролами. U>>Но теперь не совсем понятно как совмещаются controller от grails и java-класс от gwt-ext для страницы.
BAK>Тот же этот вопрос меня мучает. BAK>В своем проекте использую контроллер только для того, чтобы определить какое gwt приложение показывать. BAK>Передачу параметров в gwt-приложение осуществляю через json объекты или ajax (GWT-RPC)
Здравствуйте, mi45, Вы писали:
M>Здравствуйте, BAKAB, Вы писали:
BAK>>Здравствуйте, unreger, Вы писали:
U>>>За неделю слегка поразбирался с контролами. U>>>Но теперь не совсем понятно как совмещаются controller от grails и java-класс от gwt-ext для страницы.
BAK>>Тот же этот вопрос меня мучает. BAK>>В своем проекте использую контроллер только для того, чтобы определить какое gwt приложение показывать. BAK>>Передачу параметров в gwt-приложение осуществляю через json объекты или ajax (GWT-RPC)
M>Решение здесь: http://geekyryan.blogspot.com/2007/12/gwt-ext-and-grails-just-works.html
Спасибо за ссылку, хотя и тяжело читается.
Там используется RequestBuilder и RequestCallback из gwt,
НО, можно ведь сделать:
def listJSON = {
def testList = Test.list()
render(builder: 'json') {
totalCount(testList.size())
data { //data - название секции (произвольное) в json документе
for (t in testList) {
test(strField: t.strField, intField: t.intField)
}
}
}
}
public void onModuleLoad() {
//вывод таблицы с использованием json из контроллера
Panel panel = new Panel();
panel.setBorder(true);
panel.setPaddings(15);
panel.setWidth(700);
panel.setHeight(500);
panel.setBodyBorder(true);
HttpProxy dataProxy = new HttpProxy("/nb-gwt/test/listJSON");
RecordDef recordDef = new RecordDef(
new FieldDef[]{
new StringFieldDef("strField"),
new IntegerFieldDef("intField")
}
);
JsonReader reader = new JsonReader(recordDef);
reader.setRoot("data");
reader.setTotalProperty("totalCount");
final Store store = new Store(dataProxy, reader, true);
store.load();
ColumnModel columnModel = new ColumnModel(new ColumnConfig[]{
new ColumnConfig("Строка", "strField", 100, true),
new ColumnConfig("Число", "intField", 75, true)
});
GridPanel grid = new GridPanel();
grid.setStore(store);
grid.setColumnModel(columnModel);
grid.setWidth(375);
grid.setHeight(350);
grid.setTitle("Json Grid");
grid.setFrame(true);
grid.stripeRows(true);
grid.setIconCls("grid-icon");
panel.add(grid);
RootPanel.get().add(panel);
}
это работает, чуть позже проверю, работает ли submit и надо ли принимать в контроллере именно JSON
// из http://www.gwt-ext.com/demo/#loadSubmitXmlForm:
final Button submitBtn = new Button("Submit", new ButtonListenerAdapter() {
public void onClick(Button button, EventObject e) {
/*formPanel.getForm().submit("data/xml-errors.xml", null, Connection.GET,
"Saving Data...", false);*/
formPanel.getForm().submit("/nb-gwt/test/saveJSON"); //обращаемся к action saveJSON от TestController
}
});
U>это работает, чуть позже проверю, работает ли submit и надо ли принимать в контроллере именно JSON
вобщем вот, работает с обычным, автоматически сгенерированным action
Panel panel = new Panel();
panel.setBorder(false);
panel.setPaddings(15);
//setup form data reader
RecordDef recordDef = new RecordDef(
new FieldDef[]{
new StringFieldDef("strField"),
new IntegerFieldDef("intField")
}
);
JsonReader reader = new JsonReader(recordDef);
reader.setRoot("data");
reader.setTotalProperty("totalCount");
final FormPanel formPanel = new FormPanel(Position.RIGHT);
formPanel.setFrame(true);
formPanel.setTitle("XML Form");
formPanel.setWidth(400);
formPanel.setLabelWidth(75);
//set reader and error reader
formPanel.setReader(reader);
//add some fields
FieldSet fieldSet = new FieldSet("Contact Information");
fieldSet.add(new TextField("Строка", "strField", 100));
fieldSet.add(new TextField("Число", "intField", 75));
formPanel.add(fieldSet);
final Button submitBtn = new Button("Submit", new ButtonListenerAdapter() {
public void onClick(Button button, EventObject e) {
/*formPanel.getForm().submit("data/xml-errors.xml", null, Connection.GET,
"Saving Data...", false);*/
formPanel.getForm().submit("/nb-gwt/test/save");
}
});
formPanel.addButton(submitBtn);
panel.add(formPanel);
RootPanel.get().add(panel);
Теперь главный вопрос — как строить приложение?
Чего куда выносить. И чем лучше пользоваться. И когда.
Вот formPanel.getForm().load("/nb-gwt/test/listJSON"); или HttpProxy dataProxy = new HttpProxy("/nb-gwt/test/listJSON"); например?
то есть пишем в conf директории класс заканчивающийся на Filter и получаем перехват запросов где можем сделать тот же мехинизм идентификации. C Acegi нужно было лезть в спринг и делать практически тоже самое (что почемуто противно, к хорошему привыкаешь ). Раньше я делал через beforeInterceptor, что не удобно тем, что нужно наследоваться контроллеру от класса что не приятно, наследоваться хотчется например от другого, а во-вторых, каждому контроллер нужно было проверять, не забыл ли, а тут все сразу в одном месте. Конечно все это можно было реализвать просто сервлет-фильтрами но ведь коль в Граилс, то зачем лезть в такие дебри.
а эвенты ( http://grails.codehaus.org/GORM+-+Events)- ну это sql-триггер-подобный функционал. Раньше тоже можно было наверное перехватить .save(), delete() итд, а тут вот оно, встроенное
а за это пример рабочий сюда положи (если через фильтры будешь делать конечно)
подводя итог
совершенно разочаровался в gwt-ext
вокруг каждого компонента наворачивается десяток <div> и что-то поправить в стиле практически невозможно
так и не смог добиться нужных отступов и размеров элементов
провозился с этим в общей сложности не меньше двух недель, только маты
посмотрел альтернативы
у грайлс есть плагин для echo2
второй день разбираю — понравилось
генерация идет из groovy класса, что не может не радовать. меня.
все просто и ясно, сразу удалось сделать дизайн, который так и не осилил на gwt-ext
вверху полоса заголовка из логотипа, собственно заголовка и иногда появляющегося логина
слева баян с командами, потом центр и подвал
ненарадуюсь
рекомендую всем
ЗЫЖ напоминаю, что в груви нет inner anonimous classes, для реализации интерфейсов используются замыкания