miércoles, 13 de marzo de 2013

Exchange 2010: Traslado de buzón y libreta de direcciones no funciona

Me sucedió de repente que cuando los usuarios de outlook presionaban el botón "Para..." para poder tener acceso a la libreta de direcciones, el outlook se quedaba guindado con el mensaje "Outlook está intentando recuperar información del servidor...", y después de mucho tiempo tiraba un mensaje de error diciendo que no podía recuperar la información. No encontré nada que pudiera reparar este error, y no recordaba haber cambiado nada en el exchange para que eso ocurriera; sencillamente los usuarios ignoraban el error pero no podía solucionarlo.
 
Poco tiempo después, al crear nuevos usuarios en el dominio me di cuenta que no podía trasladar estos usuarios desde un servidor Exchange 2003 (que es el servidor de dominio) hacia mi servidor Exchange 2010 como normalmente lo hacía anteriormente. Además de esto, estos usuarios no podían consultar su correo desde Outlook Web App. Supuse que lo del Web App es porque sus buzones debían estar almacenado en el Exchange 2010, ya que es el servidor que tengo configurado para eso; pero no lograba trasladar los buzones, me decía que el tiempo de espera se había agotado, con el mensaje: "La llamada a 'net:tcp://SERVERNAME/Microsoft.Exchange.MailBoxReplicationService SERVERNAME... agotó el tiempo".
 
Me puse a investigar y encontré que la libreta de direcciones no se estaba generando y generaba un error que decía "OABGen detectó el error 80040115 al obtener acceso a Active Directory "SERVERNAME" para "".""- "\Lista de direcciones sin conexión predeterminada", por lo que supuse que tendría que ver con la comunicación entre ambos servidores. Encontré que Exchange 2010 utiliza un Client Access Server que está relacionado con la libreta de direcciones y con el OWA, pero no pude encontrar nada que solucionará el error. Pensé también que podría tener que ver algo con el certificado o cuestiones similares, pero nada.
 
Después de muchas pruebas y cuando ya estaba instalando un nuevo servidor para "limpiar" todo, me di cuenta que fallaba algo del RPC (Remote Procedure Call). Quise convertir el servidor Exchange 2010 en un DC y me tiraba un error al intentar hacer el llamado de procedimiento remoto, y también me lo tiraba en el nuevo servidor.
 
¡Pude encontrar entonces cuál era el error! Hace algunos meses había reinstalado el ISA Server, y se me había olvidado reajustar una configuración que incluso había mencionado en un post anterior: debía deshabilitar el filtro RPC. Una vez hecho esto, ¡todo el exchange volvió a la normalidad!
 
Sucedieron una serie de síntomas raros que hacían pensar que alguna cosa diferente había pasado, certificados malos, algún cambio de configuración en el exchange, permisos en el Active Directory, etc. pero era nada más una configuración en el ISA Server y que con solamente ver los foros que se referían a un solo síntoma era imposible encontrar.

viernes, 18 de enero de 2013

Crear un HorizontalScrollView programáticamente en Android

Deseaba crear un HorizontalScrollView similar al que usa Angry Birds al momento de elegir al nivel que queremos jugar, pero de manera programática porque hacerlo a través de XMLs me complicaba un poco el cálculo de los tamaños de los objetos.
 
Fue un dolor de cabeza y por más que buscaba en Internet no encontraba algún artículo que me explicara paso por paso cómo hacerlo, hasta que encontré el siguiente link que me ayudó a entender algunos conceptos: http://www.arpitonline.com/blog/2012/07/01/creating-custom-layouts-for-android/, pero además tuve que ingeniarme algunas cositas extras para hacerlo funcionar tal como quería. Posteo aquí los pasos a seguir:
  1. Crea una clase que herede de ViewGroup. ViewGroup es un View que te permite agregar Views dentro de él. Llamaremos a esta clase MyGroup. Esta clase tendrá dos objetos que nos ayudarán a crear el efecto del Scroll, además de los Views que se agregarán en él:
  2.  
    HorizontalScrollView scroll;
    LinearLayout layout;
     
  3. Dentro del constructor de MyGroup insertamos el siguiente código para agregar el scroll:
  4.  
    scroll = new HorizontalScrollView(context);
    scroll.setHorizontalScrollBarEnabled(false);
    addView(scroll);
    layout = new LinearLayout(context);
    scroll.addView(layout);
     
    HorizontalScrollView es una clase que solamente permite agregarle un hijo, éste será nuestro layout, el cual contendrá todos los views que formarán parte del scroll.
     
  5. Agrega al layout los objetos que se mostrarán en el scroll a través de la sentencia layout.addView(view).
  6.  
  7. Tal como lo describe el artículo, los objetos internos del ViewGroup no se mostrarán a menos que les indiquemos su posición y tamaño, esto lo hacemos sobreescribiendo el método onLayout. En este método, para cada view dentro de nuestro ViewGroup debemos llamar su método layout, algo similar a esto:
  8.  
    for(int i=0;i
        View v = getChildAt(i);
        v.layout(x1,y1,x2,y2);
    }
     
    Esto funciona para views simples, pero en el caso de layouts, éstos también deben indicarle a sus hijos su posición y tamaño ya que hasta ese momento tienen tamaño 0. Una forma común y sugerida en el artículo para resolver esto es sobreescribir el método onMeasure del layout para así poder indicarle a sus hijos el tamaño que tendrán. En mi caso, el único objeto que forma parte del ViewGroup es el scroll, y dentro de éste esta el layout y dentro del layout están los demás views que también deben recibir su tamaño y posición. Así que utilice el onLayout para indicar estos tamaños. Pero probando de varias maneras los objetos no salían como deseaba, hasta que me di cuenta de algo: layout debe tener un ancho igual a la suma de los anchos de sus hijos mas los espacios entre ellos, y el scroll debe tener el ancho en el que deseo aparezcan los views. Aunque puede parecer obvio, puede generar mucha confusión; si voy a poner un objeto seguido de otro sus anchos se calculan diviendo el ancho de la pantalla entre el numero de objetos, pero si quiero poner espacios entre ellos, hay que tomar en cuenta que el layout debe contemplar estos espacios y que es probable que sea incluso más grande que el scroll. El código sería algo así:
     
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        //Quiero que el scroll sea de alto la mitad de la pantalla y que esté centrado
        scroll.layout(0, b/4, r, b*3/4);
     
        //Calculo el ancho que tendrá cada objeto
        int w = (int)(b/2f*tasa);
     
        //El ancho del layout será igual a la suma de los anchos más las separaciones más la posicion inicial
        layout.layout(0, 0, (w+separacion)*(n-1)+w+pos_inicial, b/2);
     
        //Calculo la posición de los views dentro del layout
        for(int i=0; i< layout.getChildCount(); i++) {
            View v = layout.getChildAt(i);
            v.layout((w+separacion)*i+pos_inicial, 0, (w+separacion)*i+w+pos_inicial, b/2);
        }
    }
     
Una vez hecho, el scroll funcionó perfectamente en cualquier dispositivo. Ahora habrá que añadirle el onTouch y los damos eventos.
 
No es la única forma de hacerlo, pero me funcionó muy bien!