Ajuda com Javascript do Dynafaces [RESOLVIDO]

2 respostas
Luiz_Gustavo

Galera,

espero encontrar aqui no fórum alguém que possa me ajudar.
Uso em um projeto, o Woodstock, juntamente com o Dynafaces para as funcionalidades Ajax.
Até as versões beta e RC do JBoss, nunca tivemos nenhum problema com o Dynafaces. Executávamos a aplicação até mesmo no Glassfish sem problema (e até hoje a execução no Glassfish ocorre sem problemas).

No entanto, ao publicarmos a aplicação no JBoss 5GA, está ocorrendo um erro em um determinado ponto do arquivo Javascript que compõe o Dyanfaces.

O arquivo é o com_sun_faces_ajax.js, encontrado no diretório jsf-extensions-dynamic-faces-0.1\META-INF, quando se descompacta o .jar do dynafaces.

O trecho que apresenta problema está no código abaixo (somente a porção relevante de código):

/* Handles Sending Events to the Server
 ***********************************************************/
Faces.Event = Class.create();
Object.extend(Object.extend(Faces.Event.prototype, Ajax.Request.prototype), {
  initialize: function(source, options) {
  
    
    this.transport = Ajax.getTransport();
    this.setOptions(options);
	
	// make sure we are posting
	this.options.method = 'post';
	
	// get form
	this.form = DynaFaces.getForm(source);
	this.url = this.form.action;
	
	// create viewState
	var viewState = null;
	var stateOptions = new Object();

	// copy over the options that should get passed through
	Object.extend(stateOptions, this.options);
	stateOptions.source = source;
	// remove the ones that should not
	stateOptions.render = null;
	stateOptions.execute = null;
	stateOptions.asynchronous = null;
	stateOptions.contentType = null;
	stateOptions.method = null;

	viewState = new Faces.ViewState(this.form, stateOptions);
	
	// add passed parameters
	viewState.options.parameters = this.options.parameters;
	
	// initialize headers
	this.options.requestHeaders = this.options.requestHeaders || [];
	
	// guarantee our header
	this.options.requestHeaders.push(DynaFaces.gPartial);
	if (this.options.immediate) {
	    this.options.requestHeaders.push('immediate');
	}
	else {
	    this.options.requestHeaders.push('true');
	}
	
	// add methodName
	if (this.options.methodName) {
	    var sourceId = DynaFaces.$(source).id || DynaFaces.$(source).name;
		sourceId += "," + this.options.methodName;
		if (this.options.phaseId) {
			sourceId += "," + this.options.phaseId;
		}
		this.options.requestHeaders.push(DynaFaces.gMethodName);
		this.options.requestHeaders.push(sourceId);
	}

	if (this.options.execute) {
		this.options.requestHeaders.push(DynaFaces.gExecute);
		this.options.requestHeaders.push(Faces.toArray(this.options.execute,',').join(','));
	}
	
	if (this.options.render) {
		this.options.requestHeaders.push(DynaFaces.gRender);
		this.options.requestHeaders.push(Faces.toArray(this.options.render,',').join(','));
	}

	if (this.options.xjson) {
	    var xjson = DynaFaces.gJSON.object(this.options.xjson);
	    this.options.requestHeaders.push("X-JSON");
	    this.options.requestHeaders.push(xjson);
	}
	
	if (typeof DynaFaces != 'undefined') {
	    if (0 < DynaFaces._eventQueue.length) {
		this.options.requestHeaders.push(DynaFaces.gFacesEvent);
		var arr = new Array();
		for (i = 0; i < DynaFaces._eventQueue.length; i++) {
		    arr.push(DynaFaces._eventQueue[i].toString());
		}
		var events = arr.join(';');
		this.options.requestHeaders.push(events);

		// Clear out the queue
		DynaFaces._eventQueue = new Array();
	    }
	}
	if (this.options.postBody) {
	    this.options.postBody = this.options.postBody + '&' + 
		viewState.toQueryString();
	}
	else {
	    this.options.postBody = viewState.toQueryString();
	}

    var onComplete = this.options.onComplete;
    this.options.onComplete = (function(transport, xjson) {
      this.renderView(xjson);
      if (onComplete) {
	  onComplete(transport, options);
      } else if (this.doEvalResponse) {
	  this.evalResponse();
      }
    }).bind(this);

	if (this.options.onException == null) {
		this.options.onException = this.onException;
	}
	
	// send request
    this.request(this.url);
  },
  renderView: function(xjson) {
  
  
     var xml = this.transport.responseXML;     
     var id, content, markup, str;     
     
     if (null == xml || typeof xml == 'undefined') {
	 // If the content contains javaScript, just execute it
	 markup = this.transport.responseText;
	 if (null != markup && typeof markup != 'undefined') {
	     markup.evalScripts();
	 }
	 return;
     }
     
         
     var components = xml.getElementsByTagName('components')[0];
     
     var render = components.getElementsByTagName('render');
     
    
     for (var i = 0; i < render.length; i++) {

	 id = render[i].getAttribute('id');

         // join the CDATA sections in the markup
         markup = '';
         for (var j = 0; j < render[i].firstChild.childNodes.length; j++) {
	     content = render[i].firstChild.childNodes[j];
	     markup += content.text || content.data;
         }

	 str = markup.stripScripts();
	 this.doEvalResponse = false;
	 // If the user passed a replaceElement...
	 if (this.options.replaceElement) {
	     var optionType = null;
	     // look at its type.
	     if ((optionType = typeof this.options.replaceElement) != 
		 'undefined') {
		 // If its type is already a function...
		 if (optionType == 'function') {
		     // invoke it.
		     this.options.replaceElement(id, markup, 
						     this.options.closure, 
						     xjson);
		 }
		 // Otherwise, if there is a globally scoped function
		 // named as the value of the replaceElement...
		 else if (typeof DynaFaces.gGlobalScope[this.options.replaceElement] ==
			  'function') {
		     // invoke it.
		     DynaFaces.gGlobalScope[this.options.replaceElement](id, markup,
								   this.options.closure, 
								   xjson);
		 }
	     }
	 }
	 else {
	     // Otherwise, just do our element replacement.
	     DynaFaces.replace(id, str);
	 }
	 
	 // If the user specified a postReplace...
	 if (this.options.postReplace) {
         var optionType = null;
	     // look at its type.
	     if ((optionType = typeof this.options.postReplace) !=
		 'undefined') {
		 // If its type is already a function...
		 if (optionType == 'function') {
		     // invoke it.
		     this.options.postReplace(DynaFaces.$(id), markup, 
						  this.options.closure,
						  xjson);
		 }
		 // Otherwise, if there is a globally scoped function
		 // named as the value of the postReplace...
		 else if (typeof DynaFaces.gGlobalScope[this.options.postReplace] ==
			  'function') {
		     // invoke it.
		     DynaFaces.gGlobalScope[this.options.postReplace](DynaFaces.$(id), markup,
								this.options.closure,
								xjson);
		 }
	     }
	 }
	 else {
	     // Otherwise, just evaluate the scripts.
	     markup.evalScripts();
	 }
     }
   

     // This should happen for each of the elements in the collection,
     // not just the zeroth.
     var state = state || xml.getElementsByTagName('state')[0].firstChild;
     	
     if (state) {
	 var hf = DynaFaces.$(DynaFaces.gViewState);
	 if (hf) {
	     hf.value = state.text || state.data;
	 }
     }
     
  },
  evalResponse: function() {  
  	  	
	  if (this.responseIsSuccess()) {
	      var text = this.transport.responseText;	      
	      if (text) {
		  try {
		      text.evalScripts();
		  } catch (e) {}
	      }
	  }
	  
  },
  onException: function(o,e) {
	throw e;
  }
});

Neste ponto:

var components = xml.getElementsByTagName('components')[0];

components está nulo, o que não poderia acontecer em uma execução normal.

Infelizmente eu não conheço muito a fundo o Dynafaces, para saber o que todo esse código faz, e é justamente essa ajuda que estou procurando.

O que é esperado desse trecho?

xml.getElementsByTagName('components')[0]

O que eu pude enteder, do que li pelas documentações, é que essas rotinas são responsáveis por atualizar a árvore DOM da página com os componentes representados pelo xml que é manipulado neste ponto.

Bom, se alguém se dispuser a ajudar, e precisar de mais informações, estou a disposição.

Abraços!

2 Respostas

Luiz_Gustavo

Galera,

só para deixar mais claro o efeito colateral desse problema, os componentes relacionados no DynaFaces.fireAjaxTransaction para serem atualizados não o são.

Se tenho, por exemplo, dois listbox no qual a atualização do segundo depende do primeiro, hoje o que ocorre é que ao clicar em um item do primeiro os dados no backing bean são atualizados, mas a reenderização dos componentes na tela não é feita.

Grato!

Luiz_Gustavo

Galera,

consegui descobrir a solução.
O problema estava nos arquivos .jar do JSF que vieram na versão 5GA.

Eu apenas troquei os arquivos referentes ao JSF pelos que vieram no Beta4 e tudo funcionou.

Mais precisamente, eu copiei os arquivos de:

[JBOSS_HOME_BETA_4]\server\default\deployers\jbossweb.deployer\jsf-libs

para:

[JBOSS_HOME_5GA]\server\default\deploy\jbossweb.sar\jsf-libs

O que me chamou a atenção foi a diferença de tamanho desses arquivos.
Lendo a release note do JBoss 5GA, encontrei apenas essas referências a atualizações de bibliotecas:

Não consegui encontrar em nenhuma delas o JSF (não digo que não estão aí, só não consegui
encontrar a referência).

Agora aqui fica um desabafo: apesar de considerar o JBoss um bom servidor de aplicações,
me deixa F***** perder tempo com esse tipo de coisa. Ao publicar uma mesma aplicação em diferentes
versões, encontrar tantos problemas (não foi o único problema que tive com a versão 5GA).
Reconheço que as versões em questão são versões beta e final, mas ainda assim é um pé no "suvaco"
esse tipo de coisa. A mesma aplicação é publicada tranquilamente no Glassfish,
sem delongas ou tanta complicação. Fora as gambiarras necessárias para que o Netbeans reconheça o
JBoss 5GA.
Mas enfim, ainda o considero um bom servidor, e continuarei usando para outros projetos. Só lamento
essas situações.

Abraços!

Criado 10 de fevereiro de 2009
Ultima resposta 11 de fev. de 2009
Respostas 2
Participantes 1