PortBanning: URL prohibida cuando tiene un puerto especial

25 marzo, 2014 Deja un comentario

Hoy tuve un problema bloqueante mientras tenía que hacer la prueba de una aplicación vía su URL interna. Cuando hablamos de una URL interna, nos referimos a aquella que la empresa que alberga el sitio utiliza para acceder en intranet. La URL externa es aquella que todo el mundo conoce. Por ejemplo http://jomaora-prod.miempresa.com:115 con respecto de http://www.miempresa.com.

portBanning

El problema que tuve se daba cuando accedía a la página. Tenía un mensaje que decía que la URL era prohibida. Probaba la externa y no había problema, pero imposible con la interna. La razón era que el puerto que de la URL interna. En mi caso era el puerto 115, normalmente usado para el sftp, pero por alguna bizarra razón se estaba usando aca para un servicio HTTP. (Seguramente un error de algun administrador de sistemas)

Leyendo, encontré que esos puertos son bloqueados por los navigadores, por la cual la URL es prohibida. Para solucionar el problema, hay que modificar la configuración por defecto del navigador.

En el caso de Firefox hay este link http://www-archive.mozilla.org/projects/netlib/PortBanning.html

Entonces lo que hice fue buscar dónde estaba instalado forefox en mi máquina.


joan@jomaora:~$ ll /usr/bin/firefox
lrwxrwxrwx 1 root root 25 mars 18 01:24 /usr/bin/firefox -> ../lib/firefox/firefox.sh*

Fui a ese directorio


joan@jomaora:~$ cd /usr/lib/firefox
joan@jomaora:firefox$ vi defaults/pref/
channel-prefs.js vendor-gre.js

Y modifiqué el archivo vendor-gre.js agregando al final


pref("network.security.ports.banned.override", "115");

Reinicié el navigador. Y listo🙂

En Window se puede hacer lo mismo, simplement hay que ir a la carpeta ProgramFiles, buscar Mozilla Firefox y encontrar uno de los archivos js de la configuracion para agregar el valor.

Modificar path del déposito maven: -Dmaven.repo.local

16 diciembre, 2013 Deja un comentario

Cuando trabajamos con Maven, utilizamos algo que se llaman repositories o depósitos. Estos depósitos contienen los artifactos que un proyecto necesita para compilar y ejecutarse. Ellos corresponden a los jar de las dependencias del proyecto que definimos en el archivo pom.xml, del cual se hablo un poco aquí. Para mas información sobre lo qué es un depósito, ver acá.

El objetivo de estos depósitos es que cuando compilamos un proyecto, podamos recuperar los artifactos de nuestras dependecias y guardarlos en nuestra máquina de manera a reutilizarlos sin necesidad de descargarlos desde un depósito remoto como un Nexus en Jenkins. De esta manera, recuperamos artifactos de librerias comunes entre proyectos como commmons.io, commons.collections, etc. Esas dependecias son especificadas en el pom.xml del proyecto. Consideremos el siguiente ejemplo:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
_________xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
____<modelVersion>4.0.0</modelVersion>
____<groupId>com.jomaora.app</groupId>
____<artifactId>testMockito</artifactId>
____<packaging>jar</packaging>
____<version>1.5-SNAPSHOT</version>
____<name>testMockito</name>
____<build>
________<plugins>
____________<plugin>
________________<groupId>org.apache.maven.plugins</groupId>
________________<artifactId>maven-compiler-plugin</artifactId>
________________<version>2.3.2</version>
________________<configuration>
____________________<source>1.6</source>
____________________<target>1.6</target>
________________</configuration>
____________</plugin>
________</plugins>
____</build>
____<dependencies>
________<dependency>
____________<groupId>com.jomaora.app</groupId>
____________<artifactId>myproject</artifactId>
____________<version>${project.version}</version>
________</dependency>
________<dependency>
____________<groupId>com.google.guava</groupId>
____________<artifactId>guava</artifactId>
____________<version>${guava.version}</version>
________</dependency>
________<dependency>
____________<groupId>org.mockito</groupId>
____________<artifactId>mockito-core</artifactId>
____________<version>${mockito.version}</version>
________</dependency>
____</dependencies>
____<properties>
________<mockito.version>1.9.0</mockito.version>
________<guava.version>11.0.1</guava.version>
____</properties>
</project>

Cuando compilamos el proyecto (mvn clean install), las dependencias se alojan por defecto en el directorio oculto m2 de la HOME del usuario. Es fácil ubicarlas si uno lee el pom.xml. En el caso de mockito, el pom indica el groupId y el artifact que nos sirven para el path hacia el archivo, asi como la versión en la 1.9.0.

reposiroty

Ahora bien. Supongamos que tenemos dos equipos estan trabajando en evoluciones importantes sobre myproject. El equipo A trabaja en la rama (branch) dev-1.5 y el equipo B trabaja en la rama dev-1.5-big-improuvement. El equipo A tiene una fecha de entrega prevista antes que el equipo B, y tanto el equipo A como el equipo B trabajan sobre la misma máquina para hacer sus pruebas (he aquí el detalle importante del asunto).

El problema que esto presenta es que cada vez que myprojet será compilado por un equipo, el artifacto generado va a reemplazar al del otro equipo. Ejemplo:

  1. El equipo B compila el proyecto desde su rama (dev-1.5-big-impouvement) con mvn clean install, el jar de myproject se actualiza en el depósito. Luego el equipo B empaqueta la aplicación que utiliza myproject (mvn clean package) y entonces el artifacto se recupera desde el depósito.
  2. El equipo A compila el proyecto desde su branch (dev-1.5), y el jar de my project se actualiza en el depósito, reemplazando el generado por el equipo B. Problema, este nuevo artifacto no contiene los commits de la branch (dev-1.5-big-impouvement).
  3. Sin saberlo, el equipo B repite el empaquetado de la aplicación. Como el artifacto de myproject no es re compilado, la versión generada por el equipo A es recuperada y la aplicación no tendrá las modificaciones del equipo B.

Capture du 2013-11-22 18:00:00

Para evitar este problema, lo mejor es utilizar un depósito diferente para cada equipo, hasta que todas las ramas sean fusionadas (merge) en la rama a entregar. Para ello, el comando mvn de maven tiene un parámetro que permite indicar el directorio que nos servirá de depósito temporal: -Dmaven.repo.local. Ejemplo:

mvn clean install -Dmaven.repo.local=/usr/local/web/.m2/repository-equipoB 

Mock para HttpServletResponse: Test unitario para un StreamResolution

18 octubre, 2013 Deja un comentario

Stripes es un framework del que no he hablado en mis publicaciones, pero con el que trabajo todos los días. Para no entrar en detalles, Stripes es un framework utilisable en la capa de presentación que puede interfasarse fácilmente con una capa Spring de Lógica de negocio.  Uno de los principios de Stripes es que una interfaz de usuario está conectada con un ActionBean, clase que asocia cada campo de un formulario con sus atributos. Los métodos de un ActionBean pueden conectarse a los eventos del formulario y se les identifica por tener la anotación @DefaultEvent o @HandleEvent. Normalmente, estos métodos retornan un objeto de tipo Resolution, que, dando una definición ordinaria, permite la redirección de la página después del tratamiento.

Hay diferentes implementaciones de Resolution, pero la que hoy me interesa presentarles es StreamResolution. Este tipo de Resolution tiene como objetivo enviar datos al cliente más que reridigir a otra página. Uno de sus usos entonces es para presentar información en formato XML o JSON como si se tratara de un WebService. El otro día tuve que trabajar con método que efectuaba precisamente este trabajo, pero lo que me interesaba mas que la salida del flujo XML en la pantalla, era la creación de un test unitario para poder probar el código. Consideremos el siguiente método dentro de un ActionBean:

@DefaultEvent
public Resolution getResults() {
___final ResultDTO resultDTO = new ResultDTO();
___LinkedList<BookDTO> books = catalogueService.find(keyword);
___resultDTO.setBooks(books);
___XStream xStream = new XStream();
___return new StreamingResolution("text/xml", new StringReader(xStream.toXML(resultDTO)));
}

Podemos suponer que para llamar a este método pudimos haber pasado por una URL ligada al ActionBean y que el parametro keyword viene en el request. Con este valor recuperamos una lista de BookDTO que vamos luego a serializar en formato XML gracias a un objeto de la classe com.thoughtworks.xstream.XStream. Supogamos que éste tiene la siguiente estructura:

<ResultDTO>
___<books class="linked-list">
______<BookDTO>
_________<title>Maus</title>
_________<author>Art. Spiegelman</author>
______</BookDTO>
______<BookDTO>
_________<title>La Reina del Sur</title>
_________<author>Arturo Peréz Reverte</author>
______</BookDTO>
___</books>
</ResultDTO>

Ahora, lo que nos interesa es, a partir de la salida que hemos supuesto, testear el código del método. En el test unitario, además de llamar el método, debemos evaluar los valores dentro del objeto Resolution.

En debug es fácil acceder a resolution.contentType o al resolution.reader que contiene el flujo en xml. Sin embargo, esto no es posible en el test ya que estos atributos son privados. En tiempo de ejecución normal, es el objeto response que contiene también el flujo à mostrar. En este caso, podemos pasar por este objeto para recuperar esta informacion. Solo que estamos en un contexto de test Unitario, y no hay acceso a las implementaciones estandar de  es HttpServletResponse.

Para contornar este problema, existe una clase del API Spring nos permite mockear HttpServletResponse : MockHttpServletResponse. Para poder llenar las informaciones en el objeto response, debemos ademas de llamar el metodo del actionBean, invocar el método execute de la resolution, pasando precisamente como parametro el objeto response. Teniendo esto, podemos luego recuperar el ContentType y la sálida de texto. Con esto nuestro test sera:

@Test
public void verifiy_xml_conversion() throws Exception {
___when( catalogueService.find(( anyString() ) ).thenReturn(results);
___HttpServletRequest request = new MockHttpServletRequest();
___HttpServletResponse response = new MockHttpServletResponse();

___StreamingResolution resolution = (StreamingResolution) actionBean.getResults();
___resolution.execute(request, response);

___Assert.assertEquals(response.getContentType(), "text/xml");
___Assert.assertEquals( ((MockHttpServletResponse) response).getOutputString(), xmlOutPut);
}

donde xmlOutPut es un objeto String que contiene la sálida del XML que se mostró más arriba.

Identificar constraints que impiden delete en SQL. ORA-02292

9 octubre, 2013 1 comentario

Es muy común que cuando queremos hacer supresiones en una tabla de una base de datos nos veamos enfrentados con las constraint de la misma. Normalmente si la base de Datos ha sido creada con cuidado, estas constraints permiten evitar que la supresión de datos generen inconsistencias. En ese caso, ver mensajes que nos impiden suprimir los datos así como así es algo positivo.

delete from books where authorId = '9e51a7f758204f538d556049156f8f7b'

Error starting at line 1 in command:
delete from books where authorId = '9e51a7f758204f538d556049156f8f7b'
Error report:
SQL Error: ORA-02292: integrity constraint (MY_LIBRARY_SCHEMA.FK27B99837E9840F67) violated - child record found
02292. 00000 - "integrity constraint (%s.%s) violated - child record found"
*Cause: attempted to delete a parent key value that had a foreign
dependency.
*Action: delete dependencies first then parent or disable constraint.

Sin embargo, a veces estamos seguros que tenemos que eliminar ciertos datos y no necesariamente conocemos las dependencias entre las otras tablas de la base de datos y la tabla donde queremos eliminar datos. Si al momento de crear la tabla, la referencia no se hizo con ON DELETE CASCADE, la supresión no va a ser automática. Tenemos entonces que hacer un poco de retroingeniería para encontrar el order correcto de supresión. Para eso, el comando que sigue es muy práctico. Este permite encontrar el nombre de la tabla que nos impide suprimir. Para ejecutarla tenemos que estar conectados en modo administrador.

select owner, table_name from all_constraints where constraint_name = 'FK27B99837E9840F67'


OWNER                          TABLE_NAME
-----------------------------  ------------------------------
CMS4                          NODEVERSIONPUBLICATIONMETHOD


1 rows selected

Teniendo el nombre de la tabla, podemos ir a ella y ver cual es la columna que las une. Si solo hay esa constraint en la tabla, entonces suprimir en la tabla hija, bastará para poder ejecutar el delete inicial. Sino, debemos retener la constraint y seguir buscando las otras que lo impiden.

Categorías:Base de Datos Etiquetas:

Instalar jdk de Oracle en Ubuntu

8 octubre, 2013 Deja un comentario

He recibido una nueva máquina para desarrollar en el trabajo. Como cada vez que me entregan una nueva, ésta viene en Windows. Lo primero que hago es formatearla e instalar Ubuntu, esta vez, version 13.04. Luego me pongo en la tarea de instalar todos los programas, pero siempre tengo problemas para instalar el jdk. Como no quiero utilizar el openjdk que es propuesto por Ubuntu, acá mi TODO list para la próxima vez que lo quiera instalar.

  • Descargar del sitio de Oracle la versión del jdk que deseemos. En mi caso, la última versión de JDK 6 : jdk-6u45-linux-x64.bin. Es posible que sea necesario crear une cuenta Oracle para poder descargar el archivo.
  • El siguiente paso es copiar el archivo .bin en /usr/local/lib y ejecutarlo.

joan@jomaora:~$ sudo cp ~/Téléchargements/jdk-6u45-linux-x64.bin /usr/local/lib/
[sudo] password for joan:
joan@jomaora:~$ cd /usr/local/lib/

joan@jomaora:/usr/local/lib$ ./jdk-6u45-linux-x64.bin

  • Después de la ejecución, una carpeta con el jdk es creada:

joan@jomaora:/usr/local/lib$ ls
jdk1.6.0_45 jdk-6u45-linux-x64.bin python2.7 python3.3

  • Luego hay que definir las variables de entorno en el .bashrc.

export JAVA_HOME=/usr/local/lib/jdk1.6.0_45
export PATH=$PATH:$JAVA_HOME/bin

  • Con esto, desde el terminal se puede lanzar el comando java y javac y confirmar que java está correctamente instalado.

joan@jomaora:~$ java -version
java version "1.6.0_45"
Java(TM) SE Runtime Environment (build 1.6.0_45-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01, mixed mode)

joan@jomaora:~$ javac -version
javac 1.6.0_45

Categorías:Comandos Linux, Java Etiquetas: , ,

Powermockito. Whitebox y llamado de constructores privados.

7 octubre, 2013 Deja un comentario

Haciendo unos tests Unitarios, el otro día me ví confrontado a deber inicializar un objeto que no podía instanciar, ya que su constructor era privado. No recuerdo el contexto en el que me encontraba para haber llegado a esta situacion, pero lo que retuve en este ejercicio es que existe un API que nos permite utilizar los constructores privados gracias a la reflexión: PowerMockito.

Para explicar la utilización de PowerMockito, supongamos que he creado mi propia clase que representa una Map. El objetivo principal de ésta implementación es de recuperar la clave a partir de un valor. El mismo principio del get(Object) de Map, pero al revés.

diagram

En mi clase, además, un objeto no se puede instanciar porque el constructor es privado. Sin embargo, un MyMaps se obtiene via el método estático create.

public static <K, V> MyMaps<K, V> create(Map<K, V> map) {
_____return new MyMaps(map.keySet(), map.values());
}

private MyMaps(Set<K> keys, Collection<V> values) {
_____if ( keys.size() == values.size() ) {
__________size = keys.size();
__________myKeys = new ArrayList<K>(keys);
__________myValues = new ArrayList<V>(values);
_____}
}

A grandes rasgos, cuando se crea un objeto MyMaps, la Map que se le pasa en parámetro es dividida en una lista para las claves, y una para los valores. No vamos a discutir si esta representación es lógica, óptima o útil. Simplemente vamos a usarla para explicar el uso de PowerMockito.

Dentro de las clases que propone PowerMockito, tenemmos WhiteBox que permite la utilización de la reflexión en los test Unitarios. Dos métodos

permiten el llamado de métodos, en este caso, el método privado. Teniendo esto, podemos ver el código para obtener un objeto MyMaps via create y otro via WhiteBox:

Map hashMap = new HashMap<Book, Author>();
hashMap.put(author1, book1);
hashMap.put(author2, book2);

MyMaps<Book, Author> createdMap = MyMaps.create(hashMap);

MyMaps<Book, Author> privateConstructorMap = Whitebox.invokeConstructor(MyMaps.class,
_______________________new Class<?>[]{Set.class, Collection.class},
_______________________new Object[]{hashMap.keySet(), hashMap.values()});

Para ver el código completo del ejemplo utilizado, hacer clic acá (branch powermockito del proyecto). De la misma manera que llamamos un constructor usando la reflexión, otros métodos pueden ser explotados (ver invokeMethod).

Para incluir PowerMockito en las dependencias de un proyecto, agregar esto al pom:

<dependency>
___<groupId>org.powermock</groupId>
___<artifactId>powermock-api-mockito</artifactId>
___<scope>test</scope>
</dependency>
<dependency>
___<groupId>org.powermock</groupId>
___<artifactId>powermock-module-junit4</artifactId>
___<!-- para testng <artifactId>powermock-module-testng</artifactId>-->
___<scope>test</scope>
</dependency>

Retromerge y svn merge record-only

21 mayo, 2013 Deja un comentario

Retomando un poco de SVN, del hace rato no hablaba, les presento un post que tenía en borrador desde hace 6 meses. Para ponermos en contexto, voy a hablar un poco de lo que en mi equipo se llama el retromerge. Supongamos que tenemos la branch (rama) 1.1. Sobre esta branch ya no hay más desarrollos, en consecuencia no deben haber mas commits. A partir de ésta, supongamos que creamos la branch 1.2. Ya hablamos de la creación de una branch en un viejo post. Supongamos además, que sobre esta nueva branch 1.2, ya han habido dos commits. Y que uno de ellos, el n+1, corresponde a un fix urgente de un problema detectado en la 1.2, pero que también está presente en 1.1. La situación se puede resumir en la siguiente imagen:

retromerge01

En este punto alguien podría decirme que n+1 debería haber sido commiteado en la 1.1. Y estoy absolutamente de acuerdo con la apreciación, pero la situación que describo es a propósito. Además, a pesar de todo, sucede muy a menudo en el día a día de los desarrolladores. Para corregir entonces el problema en la 1.1, debemos recuperar el commit n+1 de la 1.2 y mergearlo (razón por la cual llamamos a esto retro-merge). Este merge es casi igual a los merges normales. Primero verfiquemos la lista de commits disponibles para mergear:

joan@jomaora:1.1$ svn mergeinfo http://svn.jomaora.com/proyecto/branches/1.2 --show-revs eligible
r34954
r34955

Supongamos que nuestro n+1 es la revisión 34955 (a mergear y commitear en la rama 1.1). Esta acción crea entonces un nuevo commit (Rev n+2 = 34956) que no está presente en la 1.2.

joan@jomaora:1.1$ svn merge -c 34955 http://svn.jomaora.com/proyecto/branches/1.2

retromerge02

En un mundo perfecto, este nuevo commit debe ser mergeado en la 1.2, para respectar el principio de tener todo commit de la 1.1 en la 1.2. Sin embargo, las modificaciones ya están presentes en la 1.2. Un merge normal del commit n+2 provocaría un conflicto entre los archivos mergeados debido a los cambios textuales (es decir, las líneas modificadas en el archivo). En el retromerge lo que nos interesa no es mergear estos cambios, sino indicar a la 1.2 que integraremos el commit n+2 sin tener en cuenta los cambios textuales. Para esto, utilisamos un parámetro del comande svn merge: –record-only

joan@jomaora:1.2$ svn merge --record-only -c 34956 http://svn.jomaora.com/proyecto/branches/1.1

Para verificar que el merge no ha realizado cambios textuales haciendo un svn st.

joan@jomaora:1.2$ svn st
_M .

En este caso, vemos que la M aparece en la segunda columna, indicando cambios a nivel de las propiedades svn en el directorio.

joan@jomaora:1.2 $ svn commit -m "Merging 34956 (record only from 1.1)"
Sending .

Estas operaciones podemos resumirlas en la siguiente figura:

retromerge03

Los cambios en las propiedades svn los podemos verificar utilizando el parámetro svn:mergeinfo. Con este comando podemos ver los commits que han sido mergeados como record-only.

joan@jomaora:1.2 $ svn propget svn:mergeinfo
/branches/1.1: 34956

Hype Driven Development

coz' geeks love new stuff !

My experiments with SCRUM

Site to discuss Agile (Scrum, XP, etc) concepts and ideas.

CommitStrip

Mi propia cheatsheet...

Chris Aniszczyk's (zx) diatribe

work. life. open source. diatribes.

GermanTrevi

repositorio de mi mente...