Mostrando postagens com marcador notes. Mostrar todas as postagens
Mostrando postagens com marcador notes. Mostrar todas as postagens

quarta-feira, 19 de outubro de 2011

Notes/XPages - Deletar um documento e todas seus filhos recursivamente

Bem, sabemos que um documento, em Lotus Notes, pode ter documentos filhos (Responses). E esses documentos filhos podem ter outros documentos filhos e assim vai.
Criei um Javascript Server-Side de XPages para deletar um documento e todos os seus filhos recursivamente.
Ele é bem útil para colocar em uma View, com uma coluna para deletar certo documento.

Segue o script:


function removerDocumentoComResponses(id, retornar){
 var doc:NotesDocument = database.getDocumentByUNID(id);
 var documentos:NotesDocumentCollection = doc.getResponses();
 var documentosDeleteUNID:java.util.List = new java.util.ArrayList();
 var documentoDelete:NotesDocument = documentos.getFirstDocument();
 while(documentoDelete != null){  
  if(documentoDelete.getResponses().getCount() != 0){
   documentosDeleteUNID.addAll(removerDocumentoComResponses(documentoDelete.getUniversalID(), true));
  }
  else{
   documentosDeleteUNID.add(documentoDelete.getUniversalID());
  }
  documentoDelete = documentos.getNextDocument(documentoDelete);
 }
 documentosDeleteUNID.add(doc.getUniversalID());
 documentos = null;
 if(retornar){
  return documentosDeleteUNID;
 }
 var iterator:java.util.Iterator = documentosDeleteUNID.iterator();
 while(iterator.hasNext()){
  var unid = iterator.next();
  database.getDocumentByUNID(unid).removePermanently(true);
 }
}

Esse código deve ser chamado passando o UniversalID do documento e um false no primeiro argumento.

sexta-feira, 1 de julho de 2011

Notes/XPages - Listar campos do Custom Control ou XPages atual

<Bom, a um tempo atrás tive que pegar todos os campos de dada página através de um Server-Side Javascript. Normalmente, podemos usar um getComponent("nomeDoComponent"), mas quando queremos pegar de forma geral todos os campos da página, não há um método getAllComponents.
Então criei um código recursivo que retorna uma List de components. Sendo que essa lista já contem os components, não é necessário usar getComponent.
Bem, vamos ao código:

function pegarCamposPagina(viewRoot:javax.faces.component.UIViewRoot){
    var listaCampos:java.util.ArrayList = new java.util.ArrayList();

    function iterate(component:javax.faces.component.UIComponent){
        //testa de qual tipo é o component
        if(component instanceof com.ibm.xsp.component.xp.XspInputText ||
 component instanceof com.ibm.xsp.component.xp.XspInputRichText ||
 component instanceof com.ibm.xsp.component.xp.XspInputTextarea ||
 component instanceof com.ibm.xsp.component.xp.XspInputCheckbox ||
 component instanceof com.ibm.xsp.component.xp.XspInputRadio ||
 component instanceof com.ibm.xsp.component.xp.XspSelectManyCheckbox ||
 component instanceof com.ibm.xsp.component.xp.XspSelectOneRadio ||
 component instanceof com.ibm.xsp.component.xp.XspSelectOneMenu){
            listaCampos.add(component);
        }

        //testa se o component atual tem filhos
        if(component.getChildCount() > 0){
            var lista:java.util.List = component.getChildren();
            for(var i:int=0; i<lista.size(); i++){
                iterate(lista.get(i));
            }
        }
        return null;
    }
    iterate(viewRoot);

    return listaCampos;
}

Para usar esse script, pode-se criar uma Server-Side JavaScript Library e importar na página, ou simplesmente jogar no evento. Deve-se chamar esse metodo da seguinte forma:
pegarCamposPagina(getView())

O método getView() retorna a viewRoot da página. Então enviamos para o método e ele faz chamadas recursivas até listar todos os componentes. Caso queira-se apenas os campos de uma certa table ou panel, por exemplo, é necessário passar o getComponent("nomeDoComponente") para o método. Ele também funcionará.

terça-feira, 15 de março de 2011

XPages - Trabalhando com DbColumn e DbLookup

Assim como no Notes, podemos usar @DbColumn e @DbLookup em XPages através de JavaScript. Há apenas algumas diferenças.


A sintaxe básica desses dois comandos em XPages é:

@DbLookup(dbName:string, viewName:string, key:string, colNumber:int) : any
@DbLookup(dbName:string, viewName:string, key:string, fieldName:string) : any
@DbLookup(dbName:string, viewName:string, key:string, colNumber:int, keywords:string) : any
@DbLookup(dbName:string, viewName:string, key:string, fieldName:string, keywords:string) : any
DbColumn(dbName:string, viewName:string, colNumber:int) : any

Bastante parecida com a sintaxe usada no próprio Notes.
Mas devemos ter muita atenção ao trabalhar com esses dois comandos, pois eles podem retornar: Array, String ou null. Diferente de comandos convencionais que usamos em JavaScript, esse comando pode retornar instancias diferentes de acordo com seu resultado. Caso encontre mais de um resultado, ele retorna uma instancia de Array com os resultados; caso encontre apenas um resultado, ele não retornará um Array com um elemento, mas sim o elemento; caso não encontre nada, ele retornará null. Então sempre devemos tratar os resultados de acordo com o que pode aparecer. Mas de tudo isso que falei acima, o @DbColumn tem apenas uma diferença, onde retornaria null, retorna "".

Eu sugiro usar o seguinte código ao usar esses 2 comandos:

var x = @DbLookup(@DbName(), "ViewQualquer", key, 1);
if(x instanceof Array){
    //Código para quando retornar um Array
}
else{
   if(x == null){
        //Código para quando não retornar resultados
    }
    else{
        //Código para quando retornar apenas um elemento
    }
}



var x = @DbColumn(@DbName(), "ViewQualquer", 1);
if(x instanceof Array){
    //Código para quando retornar um Array
}
else{
   if(x == ""){
        //Código para quando não retornar resultados
    }
    else{
        //Código para quando retornar apenas um elemento
    }
}

terça-feira, 1 de março de 2011

XPages - Como validar se o documento foi modificado por outro usuário

Os métodos que encontramos para validar isso costumam ser os mais complicados possíveis, geralmente dando 'lock' no documento, rodando agents, etc. Procurando como fazer isso, acabei tendo a idéia de desenvolver um simples validator que o fizesse.
Essa validação é algo muito importante, para um usuário não sobescrever o que o outro acabou de fazer e também para evitar conflitos em geral.
Bom, vamos lá.

Após já ter um NotesXspDocument definido em Data da XPage ou Custom Control, vá em eventos da página, entre no nome definido em Data por você (por padrão, document1) e então no evento "postOpenDocument". Apenas insira um evento com o seguinte código:


viewScope.acessado = @Now();


Agora crie um validator (validateExpression) em apenas UM dos campos da página. Em expression insira o seguinte código:

if(!document1.isNewNote()){
    var modificado:Date = document1.getDocument().getLastModified().toJavaDate();
    var acessado:Date = viewScope.acessado;
    return modificado.getTime() < acessado.getTime();
}
else{
    return true;
}

Agora vá em message do validator e selecione Compute value. Apenas insira o seguinte código (modificando a mensagem, caso queira):

var modificado:Date = document1.getDocument().getLastModified().toJavaDate();
return "O documentou foi modificado por outro usuário em " + modificado.toString() + ", atualize a página para evitar conflitos!";


Pronto! Agora, caso um usuário abra a página e enquanto ele edita um outro salvou, o validator irá validar isso e avisá-lo. Lembrando, é claro, que deve-se ter um Error Message vinculado ao campo ou um Error Messages na página.

segunda-feira, 28 de fevereiro de 2011

Notes/XPages - Debugando um Java Agent

Existe uma forma de debugar o Java Agent no Designer, mas é totalmente instável, o Designer trava e tem que ser fechado o tempo todo.
Então vamos usar o Eclipse para debugar nosso Agent Java. É recomendável que se deixe um eclipse apenas para isso, pois vamos mudar a JRE do Eclipse para usar a JRE do Notes. Caso use o mesmo Eclipse para outras aplicações Java, terá que ficar alterando o JRE padrão o tempo todo.

Primeiramente, crie um projeto java no eclipse como o nome que preferir. Crie a classe JavaAgent. Cole o seguinte código:
import lotus.domino.*;

public class JavaAgent extends AgentBase {

    private Database database;
    private Session session;

    public JavaAgent() {

    }

    public JavaAgent(Session s, Database d) {
        this.session = s;
        this.database = d;
    }

    //
    public static void main(String[] args) {
        Session sess=null; 
        Database db=null;
        JavaAgent ag;

        // Initialize Notes
        NotesThread.sinitThread(); 

        try {
            sess = NotesFactory.createSession();  // start a Notes session
            db = sess.getDatabase("", 

            "nomeDaDatabase.nsf");  // simulate home database for agent
            ag = new JavaAgent(sess, db);  /* simulate agent object  with session and database*/
            ag.NotesMain();   // call main routine of agent
        }
        catch(NotesException ne) {
            System.out.println(ne.id + " " + ne.text);
        }
        catch (Exception e)    {
            e.printStackTrace();
        }
        finally {
            try { 
                if (db != null) db.recycle(); 
                if (sess != null) sess.recycle(); 
            }
            catch (Exception x) {}
            NotesThread.stermThread();
        }
    }

    public void NotesMain() {
        Session session = null;
        AgentContext agentContext = null;
        try {
            if (this.session != null) // Already have an agent context.  
                {
                session = this.session;
                }
            else {  // Need to get agent context.  
                session = this.getSession();
                if (session==null) throw new 

                NotesException(NotesError.NOTES_ERR_ERROR,  "Could not get current session at start of agent.");
                agentContext = session.getAgentContext();
                if (agentContext==null) throw new 

                NotesException(NotesError.NOTES_ERR_ERROR,  "Could not get agent context at start of agent.");
                        this.database = agentContext.getCurrentDatabase();
                if (this.database==null) throw new 

                NotesException(NotesError.NOTES_ERR_ERROR,  "Could not get current database at start of agent.");
            }
        }
        catch(NotesException ne) {
            System.out.println(ne.id + " " + ne.text);
            return;
        }
        catch (Exception e)    {
            e.printStackTrace();
            return;
        }

        //Your code goes here!!!
    }
} 
 Aparecerá erros em todos os objetos do Notes, pois ainda não colocamos a JVM/JRE do Notes.

Vamos mudar o JRE do Eclipse. Vá no menu: Window > Preferences.



Vá em Java > Installed JREs.


Clique em Add, selecione Standard VM, clique em Next. Em JRE home, clique em Directory e selecione o diretório da JVM do Notes. Exemplo: C:\Program Files\IBM\Lotus\Notes\jvm

Coloque um nome de sua preferência e clique em Finish. Agora marque a JVM do Notes como padrão.

Apenas dê OK.
Agora vamos para a segunda parte. Quando você estiver programando o Java Agent no Eclipse, ele já vai usar a JVM do Notes, estando disponíveis todos comandos vindos do Notes para Java Agent. Mas também precisamos usar essa JVM na hora de executar o programa e debugar.
Vá em Run > Run Configurations.

Dê um clique duplo em Java Application para criar uma nova configuração. Coloque o nome que quiser (usei JavaAgent), selecione seu projeto e a Main Class.

Vá na aba Arguments e, caso o Working Directory não esteja já definido para o diretório de seu Notes, clique em Other e o selecione.



Certifique-se de que em JRE esteja selecionado em Runtime JRE: Project JRE (<nome que você colocou na jvm>).

Clique em Apply e Close. Agora você pode programa e debugar seu Java Agent no Eclipse.
Agora apenas modifique a linha:
db = sess.getDatabase("", "nomeDaDatabase.nsf");
colocando o nome/caminho de sua database.
Programe seu Java Agent apartir da linha:
//Your code goes here!!!

-------------------------------------------------------------
Fonte: http://www.bobzblog.com/tuxedoguy.nsf/dx/the-2-headed-beast-debugging-domino-java-agents-with-eclipse
Adaptação: Fernando Camargo