Autor |
Mensagem |
|
Fala Pedro,
quando voce diz que tem que configurar dois hibernateTemplate isso não implicaia também em dois sessionFactory??? Ou no Neo existe uma forma de configurar varios dataSources para um mesmo sessionFactory??? Eu já fiz isso no Spring mas aqui no NEO não estou conseguindo... estamos aguardando as configurações que você falou...
t+
|
 |
|
Boa tarde galera...
estou tendo problemas para implementar um crud master-detalhe em três níveis. Tenho a seguinte estrutura:
ENTIDADE
SECRETARIAS
DEPARTAMENTOS
e gostaria de implementar essa estrutura usando master-detalhe. A parte de Secretaria e Departamento já está pronta. Como era só dois níveis não houve problemas.... usei tag t:detalhe e tudo ok. Veja:
POJO:
Code:
@Entity
@Table(name="SECRETARIA")
@PrimaryKeyJoinColumn(name="CD_SECRETARIA")
public class Secretaria extends Unidade {
private static final long serialVersionUID = 1L;
private Entidade entidade;
private List<Departamento> departamentos;
// get's and set's
DAO
Code:
public class SecretariaDAO extends GenericDAO <Secretaria>{
@Override
public void updateEntradaQuery(QueryBuilder<Secretaria> query) {
query.fetchCollection("departamentos");
}
@Override
public void updateSaveOrUpdate(SaveOrUpdateStrategy save) {
save.saveOrUpdateManagedNormal("departamentos");
}
}
JSP
Code:
<%@ taglib prefix="n" uri="neo"%>
<%@ taglib prefix="t" uri="template"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<t:entrada>
<t:janelaEntrada>
<t:tabelaEntrada>
<t:property name="codigo"/>
...
<t:property name="endereco"/>
</t:tabelaEntrada>
<t:detalhe name="departamentos">
<t:property name="mascara" label="Código"/>
<t:property name="nome"/>
</t:detalhe>
</t:janelaEntrada>
</t:entrada>
No caso teria que fazer isso partindo de Entidade:
Code:
@Entity
@Table(name="ENTIDADE")
@PrimaryKeyJoinColumn(name="CD_ENTIDADE")
public class Entidade extends Unidade {
private static final long serialVersionUID = 1L;
public enum Tipo {PREFEITURA, CAMARA, AUTARQUIA, FUNDACAO}
private String CNPJ;
private Tipo tipo;
private List<Secretaria> secretarias;
....
// get's and set's
Veja que em entidade não tem nada a respeito de departamento, essa é uma informação de Secretaria...
como ficaria a implementação do DAO e do JSP?
cheguei a tentar implementar sem usar a t:detalhe conforme http://www.neoframework.org/forum/posts/list/142.page mas ficaria ruim pois, se entendi direito, o usuário teria a opção de cadastrar apenas uma secretaria por vez...
estou aberto também a soluções alternativas para o problema... na verdade preciso mostrar isso funcionando amanhã para um cliente... logo qualquer ajuda é bem vinda rsrs
um abraço vlw
|
 |
|
Hoje a noite eu tenho um compromisso.... Só se for bem mais tarde!!!! Mas faz o seguinte... defina as tarefas no JIRA que eu vou dando uma olhada e aí podemos discutir depois...
vlw
|
 |
|
vlw pessoal.. obrigado!!!
como disse, se vocês precisarem, estou disposto a colaborar nessa reestruturação...
vlw t+
|
 |
|
Fala Pedro... vou inaugurar o fórum hehehe...
Seguinte, gostaria de discutir contigo a possibilidade de fazer algumas melhorias no código do Neo de modo a facilitar a manutenção e principalmente a extensão do código, tornando mais fácil, inclusive, a implementação do NeoRIA.
Já vi alguns pontos onde, na minha opinião, poderia haver alterações... mas como estou alterando diretamente o código para im0plementar algumas Widgets (acredito que igor tenha te falado) um ponto que sempre me incomoda é a classe InputTag. Porque?
1. A classe é muito grande. Só o método doComponent() possui mais de 350 linhas. A manutenção fica muito difícil...
2. Existem tantos if's quanto linhas. A legibilidade fica extremamente prejudicada.
3. Excesso de responsabilidade. Na minha opinião o problema central da classe (vou explicar porque...)
Como disse acredito que essa classe faz mais do que deveria... eu acho que a responsabilidade de criar/inicializar cada tipo de input deveria ser realizada por classes auxiliares. A InputTag ficaria responsável apenas para identificar qual o tipo de Input a ser renderizado e delegaria a responsabilidade de criá-lo a uma classe específica. Tem uma série de recursos de OO que poderiam ser utilizados para fazer isso. Melhorando esse ponto, conseqüentemente todos os outros problemas seriam resolvidos visto que a maior parte do código seria movido pra essas classes.
Durante a implementação das Widgets eu cai num problema parecido. Todos os widgets da mootools necessitam de um código JS especifico para inicializá-lo além disso alguns como o datePicker precisa que seja inicializado já com os id's dos elementos on de ele será aplicado. Imagine aí adicionar todo o código de inicialização de um widget na InputTag!!! Não demoraria e teríamos 5000 linhas de código (rsrs)!!!
Pra resolver o problema fiz o seguinte:
Adicionei um pacote ao Neo (br.com.linkcom.neo.view.widgets[que deve existir apenas no NeoRia]) onde criei uma classe abstrata Widget conforme abaixo:
Code:
public abstract class Widget {
protected List<Object> widgets = new ArrayList<Object>();
public abstract boolean register(Object object);
public abstract String initialize();
}
Aí para cada widget a ser adicioando ao Neo é criada uma classe que o descreve. Veja como ficou o DatePicker:
Code:
public class DatePicker extends Widget {
@Override
public String initialize() {
StringBuilder sb = new StringBuilder("");
if (widgets.size() > 0) {
sb.append("<script language='javascript'>\n");
sb.append(" datePickerController.create();\n");
sb.append(" datePickerController.datePickers[\""+ datePickersToString() +"\"];\n");
sb.append("</script>");
}
return sb.toString();
}
@Override
public boolean register(Object object) {
return widgets.add(object.toString());
}
private String datePickersToString() {
StringBuilder sb = new StringBuilder("");
for (Object obj : widgets) {
sb.append(obj.toString());
sb.append(" ");
}
return sb.deleteCharAt(sb.length()-1).toString();
}
}
Por fim criei uma classe RegisterWidgetsTag conforme abaixo:
Code:
public class RegisterWidgetsTag extends BaseTag implements LogicalTag {
private static Map<Object, Widget> widgets = new HashMap<Object, Widget>();
public static void registerWidget(Object object, Class widgetClass) throws IllegalAccessException, InstantiationException {
Widget widget;
if (!widgets.containsKey(object)) {
widget = getRegistredWidget(widgetClass);
if ( widget != null) {
widget.register(object);
return;
}
widget = (Widget) widgetClass.newInstance();
widgets.put(object, widget);
widget.register(object);
}
}
@Override
protected void doComponent() throws Exception {
Set<Object> keySet = widgets.keySet();
for (Object key : keySet) {
getOut().println(widgets.get(key).initialize());
}
widgets.clear();
}
private static Widget getRegistredWidget(Class widgetClass) {
Collection<Widget> widgetList = widgets.values();
for (Widget widget : widgetList) {
if (widget.getClass() == widgetClass)
return widget;
}
return null;
}
}
e o código que eu utilizo na InputTag para registrar o datePicker é apenas Code:
RegisterWidgetsTag.registerWidget(name, DatePicker.class);
Observe que da forma como implementei (qualquer semelhança com o PropertyEditor não é mera coincidência rsrsrs) um widget só é registrado uma única vez, mesmo que exista mais de um na página (dois datePicker's por exemplo). Foi uma solução simples, que inclusive pode ser melhorada, mas que já traz um benefício significativo.
Gostaria de sua opinião, pois estou disposto modificar a InputTag reimplementando-a numa abordagem "mais OO". Nessa alteração poderíamos já fazer alguma coisa que facilitasse a extensão das Tags pelo NeoRia (o método includeJspTemplate() por exemplo).
Então é isso... desculpe pelo tópico imenso!!! Fique à vontade pra me corrigir caso esteja equivocado....
vlw
|
 |
|
fala fmpizani,
adicione o atributo trueFalseNullLabels à tag property. Assim:
Code:
<t:property name="status" label="Status" trueFalseNullLabels="Ativo,Inativo,"/>
isso deve funcionar...
vlw
|
 |
|
fala rogel... eu me coloco à disposição... se você julgar necessário tenho inclusive algumas sugestões de melhorias em alguns pontos específicos do código...
flw
|
 |
|
e aí galera...
uma coisa que considero muito importante na Web (além de interfaces bonitas) é usabilidade... não adianta colocar todos esses recursos num sistema se o usuário vai ter que a todo momento usar o mouse para acioná-los. O tempo perdido é muito grande... Dessa forma, quando pensamos em adicionar essas widgets ao NEO, pensamos também em contruir uma estrutura que permitisse ao usuário acessar todos os recursos utilizando apenas o teclado...
Acredito que dessa forma o tempo de adaptação de qualquer usuário a um sistema Web, bem como o tempo de desempenho das tarefas, seria bem menor, o que contribuiria para uma melhor aceitação dos sistemas desenvolvidos com o NEO...
vlw
|
 |
|
pedro, obrigado pela ajuda... consegui resolver o problema:
No Service modifiquei o código que setava o DataSource de
Code:
report.setDataSource(((AvaliacaoMetaDAO) getGenericDAO()).generateListToDataSource(filtro));
para
Code:
report.setDataSource(new JRBeanCollectionDataSource(((AvaliacaoMetaDAO) getGenericDAO()).generateListToDataSource(filtro)));
agora funcionou blz...
vlw t+
|
 |
|
fala pedro...
fiz a alteração que vc falou e o erro continuou a acontecer...
Code:
java.lang.NoClassDefFoundError: teste/jrml_1187702249234_715645 (wrong name: teste46jrml_1187702249234_715645)
o teste está sendo sendo feito usando o jasperreports-1.2.1.jar que acompanha o NEO.
Se eu atualizar o jar para a versão jasperreports-1.3.4.jar o erro muda e passa a ser:
Code:
java.lang.InternalError: java.io.IOException: Stream closed
flw
|
 |
|
fala pedro... como te falei to implementando apenas um teste então as classes não são muito significativas... segue abaixo:
classe que provê os dados para filtro:
Code:
public class ReportBean {
private List<String> strings;
private String nada;
public ReportBean() {
this.strings = new ArrayList<String>();
this.strings.add("Texto1");
this.strings.add("Texto2");
this.strings.add("Texto3");
this.strings.add("Texto4");
this.strings.add("Texto5");
this.strings.add("Texto6");
this.strings.add("Texto7");
this.strings.add("Texto8");
this.nada = "Nada";
}
public String getNada() {
return nada;
}
public List<String> getStrings() {
return strings;
}
public void setNada(String nada) {
this.nada = nada;
}
public void setStrings(List<String> strings) {
this.strings = strings;
}
}
bean para o relatório:
Code:
public class IReportBean {
private Integer codigo;
private String nome;
public Integer getCodigo() {
return codigo;
}
public String getNome() {
return nome;
}
public void setCodigo(Integer codigo) {
this.codigo = codigo;
}
public void setNome(String nome) {
this.nome = nome;
}
}
Controller do relatório:
Code:
@Bean
@Controller(path="/ci/relatorio/teste")
public class RelatorioController extends ReportController<ReportBean> {
private AvaliacaoMetaService avaliacaoMetaService;
public RelatorioController() {
super();
setName("relatorio");
}
@Override
public IReport createReport(WebRequestContext request, ReportBean filtro) throws Exception {
return avaliacaoMetaService.createRelatorio(filtro);
}
public void setAvaliacaoMetaService(AvaliacaoMetaService avaliacaoMetaService) {
this.avaliacaoMetaService = avaliacaoMetaService;
}
}
Service:
Code:
public class AvaliacaoMetaService extends GenericService<AvaliacaoMeta> {
public IReport createRelatorio(ReportBean filtro) {
Report report = new Report("teste");
report.setDataSource(((AvaliacaoMetaDAO) getGenericDAO()).generateListToDataSource(filtro));
return report;
}
}
DAO:
Code:
public class AvaliacaoMetaDAO extends GenericDAO<AvaliacaoMeta> {
public List<IReportBean> generateListToDataSource(ReportBean filtro) {
List<IReportBean> dados = new ArrayList<IReportBean>();
for(int i = 0; i < filtro.getStrings().size(); i++) {
IReportBean bean = new IReportBean();
bean.setCodigo(i);
bean.setNome(filtro.getStrings().get(i));
dados.add(bean);
}
return dados;
}
}
relatorio.jsp
Code:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="n" uri="neo"%>
<%@ taglib prefix="t" uri="template"%>
<t:tela titulo="Coleta de dados">
<t:janelaFiltro>
<t:tabelaFiltro showSubmit="false">
<n:group>
<n:submit url="/ci/relatorio/teste" action="gerar">Gerar Relatório</n:submit>
</n:group>
</t:tabelaFiltro>
</t:janelaFiltro>
</t:tela>
Estrutura de Pastas:
relatorio.jsp => WEB-INF/jsp/ci/relatorio onde ci é o nome do módulo configurado
teste.jrml e teste.jasper => WEB-INF/relatorio
acho que é só isso... se precisar de mais alguma coisa é só falar...
cara só mais uma coisa... observando os fontes do NEO observei que voces passam um objeto JasperReport para ser preenchido... nunca tinha usado essa abodagem, eu sempre passava o relatório compilado (.jasper). Sempre achei que passando o .jasper o processamento seria mais rápido. Isso é correto ou estou enganado?
Só esclarecendo... não é minha intenção questionar a forma de voces implementarem... sempre faço essas perguntas para entender os motivos que os levaram a adotar uma determinada abordagem procurando sempre aperfeicoar a minha forma de desenvolver...
vlw t+
|
 |
|
E aí pedro blz...
cara, tentei implementar um teste de relatório aqui de acordo com as informações que vc passou... tive alguns problemas e queria ve contigo onde estou errando...
o erro é o seguinte:
Code:
java.lang.NoClassDefFoundError: teste/jrml_1187702249234_715645 (wrong name: teste46jrml_1187702249234_715645)
olhando o fonte do NEO o erro acontece no método public byte[] toPdf(IReport report) throws ReportException na classe br.com.linkcom.neo.report.ReportGeneratorImpl mais especificamente no momento em que ele vai preencher e exportar o relatório para Pdf
Code:
return JasperRunManager.runReportToPdf(jasperReport, allParameters, dataSource);
Achei que poderia ser algum problema de versão na compilação, visto que uso o jasperreports-1.3.4.jar e o NEO usa o jasperreports-1.2.1.jar, então eu alterei o jasper do NEO colocando a minha versão... quando fiz isso o erro anterior deixou de existir e comecou a dá outro erro
Code:
java.lang.InternalError: java.io.IOException: Stream closed
se vc quiser eu posso passar os fontes das classes...
vlw cara, fico no aguardo...
t+
|
 |
|
pessoal,
retirando de TODOS os campos o nullable=false funcionou... mas acho que o NEO deveria permitir que se configurasse o hibernate ao critério do desenvolvedor. Nesse caso, por exemplo, vou ter q retirar de todas as classes de mapeamento o nullable=false.
De qualquer forma, obrigado a todos pela ajuda...
t+
|
 |
|
fala pedro... como tinha dito acima o problema da duplicação já foi resolvido... meu problema agora é quando eu tento excluir um registro... ele dá o seguinte erro:
Code:
* not-null property references a null or transient value: br.inf.mastersoft.agil.ci.pojo.metas.Meta.nome; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: br.inf.mastersoft.agil.ci.pojo.metas.Meta.nome
o not-null property references a null or transient value: br.inf.mastersoft.agil.ci.pojo.metas.Meta.nome
o código do DAO e do mapeamanto de estão postados acima... alguma idéia do que fiz de errado????
vlw, fico no aguardo....
|
 |
|
e aí pessoal...
alguma idéia de como posso fazer para resolver esse problema ao deletar um registro...
fico no aguardo... flw
|
 |
|