Customizando o Cartão de Visita do IBM Sametime
Migrei o artigo "Customizando o Cartão de Visita do IBM Sametime" da IBM developerWorks, após a venda do Sametime para a HCL.
Resumo
Ter acesso a informação dos colegas de trabalho no dia a dia deve ser fácil e rápido. Este artigo descreve de forma prática como disponibilizar essas informações através dos IBM Sametime Connect Client e do IBM Sametime Web Client (Sametime Proxy Server).
Introdução
A nossa história começa com um Multinacional que há um ano atrás disponibilizou para seu funcionários o IBM Sametime e o IBM Connections. Hoje, através dessas duas ferramentas os empregados comunicam melhor e de forma mais efetiva.
Em uma certa manhã, o Diretor de TI da empresa retorna de uma reunião com a Vice-Presidente de Marketing. O Departamento de Marketing solicitava que novas informações fossem apresentados no Cartão de Visita do IBM Sametime
O Cartão de Visita do IBM Sametime Connect Cliente e Web Client apresenta informações sobre o Contato, incluindo Nome, Título, Telefone e até Fotos. Os usuários visualizam essas informações quando estão numa janela de Chat ou quando passam o ponteiro do mouse sobre um contato na Lista de Contatos.
ADICIONAR TELA COM O BUSINESS CARD
Figura 1: Tela com o Business Card
O Diretor de TI lança o desafio ao Administrador do IBM Sametime de atender as demandas a seguir:
1. Adicionar novos campos provenientes do LDAP;
2. Adicionar campos provenientes do Sistema de RH da Empresa;
3. Apresentar a foto do usuário armazenada no Perfil do IBM Connections;
De posse dessas necessidades o Administrador do IBM Sametime começa as customizações.
1. Adicionando novos Campos provenientes do LDAP
Por padrão, A interface de configuração do Cartão de Vista do Sametime System Console permitem selecionar quais informações serão apresentadas no cliente Sametime.
1.1. Alterando os atributos através do Sametime System Console
Os atributos disponíveis são:
- Nome (Name)
- Empresa (Company)
- Telefone (Telephone)
- Endereço (Location)
- Título (Title)
- Foto (Photo)
Como as informações do Cartão de Visita são obtidas do Diretório LDAP ao qual o servidor IBM Sametime Community Server esta configurado, devemos mapear os atributos:
Você pode alterar o Cartão de Visita através do Sametime System Console.
Siga os Passos:
1) Acesse Sametime System Console
2) Na navegação (à esquerda) , clique em Sametime System Console
3) Expanda Servidores do Sametime e clique em Servidores da Comunidade Sametime.
4) Clique no Identificador de Implementação (Deployment Plan) do Servidor Sametime Community.
5) Clique na aba Cartão de Visita.
6) Altere os atributos, clique OK para salvar as configurações
Reinicie o servidor Sametime Community Server.
Figura 2: Configuração do Cartão de Visita no Sametime System Console
Apesar da facilidade de utilização do Console de Administração do Sametime, ficamos limitados aos campos disponíveis. Além disso, nem todas as informações do usuário ficam armazenadas em único repositório, como um diretório LDAP, devido a questões de performance. Um exemplo, seria as fotos dos usuários.
1.2. O subsistema de Cartão de Visita
O subsistema de Cartão de Visita do IBM Sametime busca as informações dos repositórios configurados no arquivo UserInfoConfig.xml.
Estes repositórios podem ser:
- Um diretório LDAP - Um aplicação Notes - Uma classe Java, que por sua vez busca informações em uma base SQL ou em um ERP/SAP.
A interface (API) que faz acesso a esses repositório que é chamada de BlackBox.
O processo de busca das informações pelo Cliente no repositório é descrito abaixo:
1) o Cliente Sametime faz uma requisição HTTP (GET) a um servidor Sametime Community.
2) Quando a requisição chega no servidor HTTP do Sametime/Domino, o Domino redireciona o request para o servlet UserInfoServlet
3) O servlet UserInfoServlet, por sua vez lê o arquivo UserInfoConfig.xml, a qual tem as informações de conexão aos repositórios.
4) O servlet consulta cada repositório em busca das informações
5) Os dados dos repositórios são retornadas ao servlet UserInfo
6) O servlet combina as respostas destes repositórios e converte em um documento XML.
7) O servidor HTTP envia o documento XML para o cliente, que extrai os dados e apresenta no cliente.
Figura 3: Configuração do Cartão de Visita no Sametime System Console
1.3. Adicionando atributos através do UserInfoConfig.xml
O arquivo UserInfoConfig.xml permite uma maior flexibilidade na customização dos dados apresentados no Cartão de Visita.
O arquivo é gerado durante a instalação do Servidor Sametime Community e fica localizado no seguinte diretório (conforme a plataforma):
MS Windows:
<DOMINO_INSTALL_DIR>\UserInfoConfig.xml.
Exemplo: C:\IBM\Domino\UserInfoConfig.xml.
Linux/AIX:
<DOMINO_DATA>\UserInfoConfig.xml
Exemplo: /local/notesdata
Ao abrirmos o arquivo UserInfoConfig.xml, você poderá observar, basicamente, duas seções:
Na seção <Storage type="LDAP">, temos as informações de conexão ao servidor LDAP
<Storage type="LDAP"> <StorageDetails HostName="ldapserver_hostname" Port="636" UserName="" Password="" SslEnabled="false" SslPort="636" BaseDN="" Scope="2" SearchFilter="(& (objectclass=organizationalPerson)(|(cn=%s)(givenname=%s)(sn=%s)(mail=%s)))"/> <!-- Add another StorageDetails tag to support another ldap server. The listing order implies the searching order --> <!-- Scope: 0=OBJECT_SCOPE 1=ONELEVEL_SCOPE 2=SUBTREE_SCOPE-->
Listagem 1: Seção com as informações de conexão ao LDAP
Enquanto na seção Details, temos o mapeamento entre os Atributos do Sametime e do LDAP
<Details> <Detail Id="MailAddress" FieldName="mail" Type="text/plain"/> <Detail Id="Name" FieldName="cn" Type="text/plain"/> <Detail Id="Title" FieldName="title" Type="text/plain"/> <Detail Id="Location" FieldName="postalAddress" Type="text/plain"/> <Detail Id="Telephone" FieldName="telephoneNumber" Type="text/plain"/> <Detail Id="Company" FieldName="ou" Type="text/plain" /> <Detail Id="Photo" FieldName="jpegPhoto" Type="image/jpeg" /> </Details> </Storage> </Resources> <ParamsSets> <Set SetId="0" params="MailAddress,Name,Title,Location,Telephone,Photo,Company"/> <Set SetId="1" params="MailAddress,Name,Title,Location,Telephone,Photo,Company"/> </ParamsSets>
Listagem 2: Seção com o mapeamento dos atributos
Vamos começar então o procedimento para adicionar novos campos:
Procedimento:
Antes de iniciarmos devemos por precaução realizar um backup do arquivo UserInfoConfig.xml
1) Edite o arquivo UserInfoConfig.xml
2) Localize a seção Details
3) Localize a entrada Telephone e vamos incluir o número do Celular.
<Detail Id="Telephone" FieldName="telephoneNumber,mobile" Type="text/plain" DisplaySeparator=" / " />
4) Antes da tag </Details>, vamos adicionar agora dois novos campos, como abaixo:
<Detail Id="State" FieldName="stateOrProvince" Type="text/plain"/>
<Detail Id="City" FieldName="city" Type="text/plain"/>
5) Localize a seção ParamsSets e adicione os novos campos
<ParamsSets> <Set SetId="0" params="MailAddress,Name,Title,Location,Telephone,Photo,Company,City,State"/> <Set SetId="1" params="MailAddress,Name,Title,Location,Telephone,Photo,Company,City,State"/> </ParamsSets>
6) Salve e Feche o arquivo.
O arquivo final fica da seguinte maneira:
<Details> <Detail Id="MailAddress" FieldName="mail" Type="text/plain"/> <Detail Id="Name" FieldName="cn" Type="text/plain"/> <Detail Id="Title" FieldName="title" Type="text/plain"cod/> <Detail Id="Location" FieldName="postalAddress" Type="text/plain"/> <Detail Id="Telephone" FieldName="telephoneNumber,mobile" Type="text/plain" DisplaySeparator=" / " /> <Detail Id="Company" FieldName="ou" Type="text/plain" /> <Detail Id="Photo" FieldName="jpegPhoto" Type="image/jpeg" /> <Detail Id="State" FieldName="stateOrProvince" Type="text/plain"/> <Detail Id="City" FieldName="city" Type="text/plain"/> </Details> </Storage> </Resources> <ParamsSets> <Set SetId="0" params="MailAddress,Name,Title,Location,Telephone,Photo,Company,City,State"/> <Set SetId="1" params="MailAddress,Name,Title,Location,Telephone,Photo,Company,City,State"/> </ParamsSets>
Listagem 3: Resultado das alterações sobre o arquivo UserInfoConfig.xml
7) Reinicie o servidor Sametime Community
Para testar o resultado da alteração do UserInfoConfig.xml, você pode verificar o resultado retornado pelo servlet UserInfoServlet.
Em um navegador, entre com o endereço
http://<Sametime_Server>/servlet/UserInfoServlet?operation=3&setid=2&userid=<Test_Account_Name>
onde:
Exemplo:
http://stserver/servlet/UserInfoServlet?operation=3&setid=2&userid=uid=ebasso
Onde o resultado
<?xml version="1.0" encoding="UTF-8"?>
<userinfo>
<user id ="uid=ebasso">
<field name="MailAddress" type="" error="UNAVAILABLE"/>
<field name="Name" type="text/plain">Enio Rubens Basso</field>
<field name="Title" type="text/plain">Especialista de TI</field>
<field name="Location" type="" error="UNAVAILABLE"/>
<field name="Telephone" type="text/plain">61-3333-4444 / 61-9999-9999</field>
<field name="City" type="text/plain">Brasilia</field>
<field name="State" type="text/plain">DF</field>
</user>
</userinfo>
Listagem 4: Retorno do servlet
Como você pode ver, caso o valor de uma atributo no LDAP não esteja populado, o UserInfoServlet retorna error="UNAVAILABLE".
Adicionar campos provenientes do Sistema de RH da Empresa
Para atender o segundo desafio do departamento de Marketing, o Administrador do Sametime, precisa buscar as informações que se encontram no Sistema de RH da Empresa.
Para evitar realizar consultas a todo momento no Sistema de RH, vamos criar um repositório local para armazenar as informações a serem apresentadas no Cartão de Visita do Sametime.
Para realizar esta tarefa precisamos realizar 3 atividades:
- Criar o repositório local
- Importar os dados do Sistema de RH
- Configurar o UserInfoConfig.xml.
Como pré requisito da tarefa, você vai precisar ter um Domino Designer instalado no seu computador, e configurado para acessar o servidor do Sametime Comunity. Utilize o usuario Administrador do Sametime para que nao tenha restricoes na criacao da database e de execucao no servidor.
2.1. Criando o repositório local
Vamos criar uma aplicacao Notes (NSF) para armazenar os dados.
1) Abra o Domino Designer
2) Crie a nova base, atraves do menu File -> Application -> New
Informe os seguintes campos
Clique em OK
'
'
Figura 4: Caixa de Dialogo para criar uma nova aplicação
Vamos criar agora o formulario
4) Crie o novo formulario, atraves do menu Create -> Design -> Form
Clique em OK
5) Crie o campo chave, denominado uid. Atraves do menu Create -> Design -> Field.
Informe no campo Name, o valor uid , defina como tipo Text.
Figura 5: Caixa de Dialogo para criar uma novo campo
6) Vamos criar os demais campos usados neste artigo.
Salve o formulario, atraves do menu File -> Save.
Figura 6: Novos campos criados
Vamos criar a visao de indice
7) Crie uma nova visao, atraves do menu Create -> Design -> View
Informe:
Clique em Save and Customize
Figura 6: Caixa de Dialogo para criar visao
8) Clique na coluna #, selecione Field e selecione uid.
Figura 7: Definindo o valor da coluna
9) Na caixa de dialogo de propriedades, clique na segunda aba e em sort clique em Ascending.
Figura 8: Definindo o tipo de ordenacao
Salve a visao, atraves do menu File -> Save.
Agora ja possuimos uma repositorio secundario local.
2.2. Importando os dados do Sistema de RH
O Sistema de RH da empresa fica armazenado em um banco de Dados DB2.
Nesta seção o vamos criar um agente na linguagem Java para buscar as informacoes da base de dados SQL , e popular o repositorio NSF local.
O nosso agente esta divido em 5 partes:
1) Definicao das variaveis 2) Inicializacao do Driver JDBC do DB2 3) Execucao da query 4) Criacao ou Atualizacao do documento no repositorio NSF 5) Metodo principal
Preparação:
Como preparação para o acesso ao DB2, devemos adicionar os drivers JDBC (tipo 4) do DB2.
Dentro do diretorio <DOMINO_INSTALL_DIR>\ibm-jre\jre\lib\ext, devemos copiar os arquivos:
- db2jcc.jar
- db2jcc_license_cu.jar
Figura 9: Configuracao dos drivers JDBC do DB2
Procedimento:
1) Crie o novo atraves do menu Create -> Design -> Agent
Clique em OK
2) Em Basics, defina On Schedule -> Daily, em Target defina None.
'
3) Em Security, defina 3. Allow restricted operations with full administration rights.
4) Click em JavaAgent.java para criarmos o codigo.
5) Dentro da Classe JavaAgent, devemos definir as contantes de conexao ao DB2, variaveis globais a classe, ...
// CONSTANTES private static final String JDBC_CLASS = "com.ibm.db2.jcc.DB2Driver"; private static final String JDBC_URL = "jdbc:db2://db2srv.empresax.com.br:50000/RHS"; private static final String JDBC_USERID = "STUSER"; private static final String JDBC_PASSWORD = "STUSER"; private static final String UID_LOOKUP_VIEW_NAME = "vwIndex"; private static final String SQL = "SELECT UID, DPTO " + "FROM EMPLOYEE " + "ORDER BY UID"; // VARIAVEIS GLOBAIS A CLASSE Connection con; String uid = ""; String dpto = "";
6) Inicializacao do Driver JDBC do DB2
private void initDB() throws Exception { // Load the requested JDBC driver type Class.forName(JDBC_CLASS).newInstance(); con = DriverManager.getConnection(JDBC_URL, JDBC_USERID, JDBC_PASSWORD); }
7) Execucao da query
Para cada linha retornada pelo SELECT, vamos chamar o metodo updateOrCreateDocument.
private void runMain(Database db) throws Exception { Statement stmt = con.createStatement(); System.out.println("runQuery - start"); ResultSet rs = stmt.executeQuery(SQL); System.out.println("runQuery - end"); int i=0;
System.out.println("Iterating: " + i);
while (rs.next()) {
if (++i % 1000 == 0) {
System.out.println("Iterating: " + i);
}
uid = rs.getString("UID");
if (uid == null) uid = "";
dpto = rs.getString("DPTO");
if (dpto == null) dpto = "";
updateOrCreateDocument(db,uid);
}
stmt.close();
System.out.println("Total: " + i);
}
8) Criacao ou Atualizacao do documento no repositorio NSF
Com a chave primaria, armazenada na string key, verificamos a existencia ou nao do documento. Se o resultado for vazio, criamos um novo documento senao verificamos por mudancas e entao atualizamos o documento.
private void updateOrCreateDocument(Database db, String key) throws Exception {
View view = db.getView(UID_LOOKUP_VIEW_NAME);
Document doc = null;
boolean saveDoc = false;
doc = view.getDocumentByKey(key, true);
if (doc == null){
doc = db.createDocument();
doc.replaceItemValue("Form","person");
doc.replaceItemValue("uid", uid);
doc.replaceItemValue("dpto", dpto);
saveDoc = true;
} else {
if (!uid.equals("") && !uid.equals(doc.getItemValueString("uid"))){
doc.replaceItemValue("uid", uid);
saveDoc = true;
}
if (!dpto.equals("") && !dpto.equals(doc.getItemValueString("dpto"))){
doc.replaceItemValue("dpto", dpto);
saveDoc = true;
}
}
if (saveDoc) {
doc.save(true, false, true);
}
doc.recycle();
view.recycle();
}
9) No metodo principal NotesMain, chamamos os demais metodos.
public void NotesMain() {
try {
Session session = getSession();
AgentContext agentContext = session.getAgentContext();
// (Your code goes here)
Database notedDb = agentContext.getCurrentDatabase();
System.out.println("ImportPersonInfo - start");
initDB();
runMain(notedDb);
System.out.println("ImportPersonInfo - end");
} catch(Exception e) {
e.printStackTrace();
}
}
2.3. Configurando o UserInfoConfig.xml para utilizar o repositorio local
Como um pre-requisito para a desta secao eh termos uma chave primaria entre o primeiro repositorio LDAP e o segundo repositorio NSF. Neste caso o valor do campo uid sera populado com os mesmos valores.
1) Edite o arquivo UserInfoConfig.xml
2) Localize a tag </Storage>, e adicione o novo repositorio:
<Storage type="NOTES_CUSTOM_DB"> <StorageDetails DbName="secbookstore.nsf" View="vwIndex"/> <Details> <Detail Id="Dpto" FieldName="Dpto" Type="text/plain"/> <Detail Id="PhotoURL" FieldName="PhotoURL" Type="text/plain"/> <Detail Id="Photo" FieldName="photo" Type="image/jpeg" /> </Details> </Storage> '
3) Localize a seção <ParamsSets> e adicione os novos campos
<ParamsSets> <Set SetId="0" params="MailAddress,Name,Title,Location,Telephone,Photo,Company,City,State,Dpto"/> <Set SetId="1" params="MailAddress,Name,Title,Location,Telephone,Photo,Company,City,State,Dpto"/> </ParamsSets>
4) Localize a seção <BlackBoxConfiguration> e adicione os novos blackbox
<BlackBox type="NOTES_CUSTOM_DB" name="com.ibm.sametime.userinfo.userinfobb.UserInfoNotesCustomBB" MaxInstances="4"/>
5) Salve e Feche o arquivo.
6) Reinicie o servidor Sametime Community
3. Apresentar a foto do usuário armazenada no Perfil do IBM Connections
Por fim iremos utilizar as fotos armazenadas nos Perfis do IBM Connections para serem apresentadas nos IBM Sametime.
No IBM Connections, as fotos do Perfis ficam armazenados no banco de dados, dentro da tabela EMPINST.PHOTO. O acesso direto as tabelas do Perfis nao eh suportado pela IBM, mas iremos utilizar aqui neste artigo.
Aqui vamos adicionar adicionar 2 campos principais:
- Photo: Campo RichText utilizado para armazenar o binario da foto utilizada pelo Sametime Connect Client
PhotoURL: Url da foto utilizado pelo Sametime Web Client (Sametime Proxy)
Para evitar a comparacao de 2 arquivos, criamos o campo updated, a qual possui a data de alteracao do arquivo de foto.
3.1. Importando as fotos do IBM Connections
O nosso agente esta divido em 6 partes:
1) Definicao das variaveis
2) Inicializacao do Driver JDBC do DB2
3) Execucao da query
4) Criar o arquivo de Imagem
5) Criacao ou Atualizacao do documento no repositorio NSF
6) Metodo principal
Por se tratar da mesma abordagem usada na secao anterior, vamos apresentar apenas as diferencas
Procedimento:
1) Crie o novo atraves do menu Create -> Design -> Agent
Clique em OK
'
Repita os passos 2, 3, 4 do item 2.2.
5) Dentro da Classe JavaAgent, vamos adicionar novas contantes de conexao ao DB2, variaveis globais a classe, ...
private static final String PHOTOS_TEMP_DIRECTORY = "c:\\temp\\fotos\\img_";
private static final String PHOTO_URL_PREFIX = "http://connections.empresax.com.br/profiles/photo.do?uid=%22;
private static final String SQL =
"SELECT E.PROF_UID UID, P.PROF_UPDATED UPDATED, P.PROF_IMAGE IMAGE " +
"FROM EMPINST.PHOTO P, " +
"EMPINST.EMPLOYEE E " +
"WHERE P.PROF_KEY=E.PROF_KEY";
String updated = "";
byte[] photo_bytes ;
A variavel PHOTOS_TEMP_DIRECTORY armazena o diretorio temporario para armazenar as fotos.
A variavel PHOTO_URL_PREFIX armazena a url para busca das fotos no IBM Connections.
Repita os passos 6 do item 2.2.
7) Execucao da query
Para cada linha retornada pelo SELECT, eh necessario criar um arquivo com a foto do usuario em um diretorio temporario, atraves do metodo createImageFile, logo depois devemos chamar o metodo updateOrCreateDocument.
private String createImageFile(String uid) throws Exception {
String filename = PHOTOS_TEMP_DIRECTORY + uid + ".jpg";
File outFile = new File(filename);
FileOutputStream fos = new FileOutputStream(outFile);
fos.write(photo_bytes);
fos.close();
return filename;
}
private void runMain(Database db) throws Exception {
Statement stmt = con.createStatement();
System.out.println("runQuery - start");
ResultSet rs = stmt.executeQuery(SQL);
System.out.println("runQuery - end");
int i=0;
System.out.println("Iterating: " + i);
while (rs.next()) {
if (++i % 1000 == 0) {
System.out.println("Iterating: " + i);
}
uid = rs.getString("UID");
if (uid == null) uid = "";
updated = rs.getString("UPDATED");
photo_bytes = rs.getBytes("IMAGE");
String filename = createImageFile(uid);
updateOrCreateDocument(db,uid,filename);
}
stmt.close();
System.out.println("Total: " + i);
}
8) Criacao ou Atualizacao do documento no repositorio NSF
Com a chave primaria, armazenada na string key, verificamos a existencia ou nao do documento. Se o resultado for vazio, criamos um novo documento senao verificamos por mudancas e entao atualizamos o documento.
private void updateOrCreateDocument(Database db, String key) throws Exception {
View view = db.getView(UID_LOOKUP_VIEW_NAME);
Document doc = null;
boolean saveDoc = false;
doc = view.getDocumentByKey(key, true);
if (doc == null){
doc = db.createDocument();
doc.replaceItemValue("Form","person");
doc.replaceItemValue("uid", uid);
doc.replaceItemValue("updated", updated);
doc.replaceItemValue("PhotoURL", PHOTO_URL_PREFIX + uid);
photo = doc.createRichTextItem("photo");
photo.embedObject(EmbeddedObject.EMBED_ATTACHMENT, null, filename, null);
saveDoc = true;
} else {
if (!uid.equals("") && !uid.equals(doc.getItemValueString("uid"))){
doc.replaceItemValue("uid", uid);
saveDoc = true;
}
if (!updated.equals("") && !updated.equals(doc.getItemValueString("updated"))){
doc.replaceItemValue("updated", updated);
doc.removeItem("photo");
doc.replaceItemValue("PhotoURL", PHOTO_URL_PREFIX + uid);
photo = doc.createRichTextItem("photo");
photo.embedObject(EmbeddedObject.EMBED_ATTACHMENT, null, filename, null);
saveDoc = true;
}
}
if (saveDoc) {
doc.save(true, false, true);
}
doc.recycle();
view.recycle();
}
9) No metodo principal NotesMain, chamamos os demais metodos.
3.2. Configurando o UserInfoConfig.xml para retornar as fotos.
1) Edite o arquivo UserInfoConfig.xml
2) Localize a secao <Storage>, e adicione o novos campos:
<Storage type="NOTES_CUSTOM_DB"> <StorageDetails DbName="secbookstore.nsf" View="vwIndex"/> <Details> <Detail Id="Dpto" FieldName="Dpto" Type="text/plain"/> <Detail Id="PhotoURL" FieldName="PhotoURL" Type="text/plain"/> <Detail Id="Photo" FieldName="photo" Type="image/jpeg" /> </Details> </Storage>
3) Salve e Feche o arquivo.
4) Reinicie o servidor Sametime Community
Conclusão
Este artigo descreveu como extender o IBM Sametime para prover informações aos usuários armazenadas em diversos repositórios. Mostramos como criar um repositório próprio buscando informações de outras fontes como um base SQL. E importando as fotos dos perfis do IBM Connections.
Caso voce tenha um Cluster de IBM Sametime Community Server, basta criar uma replica da base secbookstore.nsf e copiar o arquivo UserInfoConfig.xml para os demais servidores.
Espero que o artigo seja útil no seu dia como Administrador Sametime.
Recursos
Ver também