tag:blogger.com,1999:blog-46727184240223818652024-02-06T18:12:56.005-08:00A piece of my codeGabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.comBlogger171125tag:blogger.com,1999:blog-4672718424022381865.post-75300520950435263892016-03-14T20:47:00.001-07:002016-03-14T20:47:23.384-07:00Enums: Campos de arregloUsando arreglos en campos del enum. En este ejemplo utilizado para agragar los lenguajes soportados por una tienda.
<br />
<br />
<pre class="brush:java">public enum StoreCode {
BR(Language.pt_BR, Subdomain.BR, Language.pt_BR, Language.en),
US(Language.en_US, Subdomain.WWW, Language.en_US)
// ....
;
private final Language defaultLanguage;
private final Language [] supportedLanguages;
private final Subdomain subdomain;
StoreCode(Language defaultLanguage, Subdomain subdomain, Language ... supportedLanguages) {
this.defaultLanguage = defaultLanguage;
this.subdomain = subdomain;
this.supportedLanguages = supportedLanguages;
}
public Language getDefaultLanguage() {
return defaultLanguage;
}
public Subdomain getSubdomain() {
return subdomain;
}
public Language[] getSupportedLanguages() {
return supportedLanguages;
}
}
</pre>
Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-41466116048662357722016-02-12T20:44:00.000-08:002016-02-12T20:45:33.210-08:00Enums: Buscando valores de manera invertidaUn tip interesante para simplificar la búsqueda en un enum por alguna de sus propiedades. En este ejemplo tenemos un enum para tiendas de países. Una de sus propiedades es el subdominio. Si queremos tener un método para retornar el valor de la tienda usando como entrada el subdominio, podemos preparar un mapa de manera estática donde la llave es el subdominio.
<pre class="brush:java">
public enum CountryStore {
AD(Language.en, Measures.METRIC, Subdomain.AND),
AE(Language.en, Measures.METRIC, Subdomain.AE),
AF(Language.en, Measures.METRIC, Subdomain.AF),
...
private final Language defaultLanguage;
private final Measures defaultMeasure;
private final Subdomain subdomain;
CountryStore(Language defaultLanguage, Measures defaultMeasure, Subdomain subdomain) {
this.defaultLanguage = defaultLanguage;
this.defaultMeasure = defaultMeasure;
this.subdomain = subdomain;
}
private final static Map<String, StoreCode> subdomainMap;
static {
// Reverse lookup preparation for subdomains.
Map<String, CountryStore> smap = new HashMap<String, CountryStore>();
for(CountryStore store: CountryStore.values()) {
smap.put(store.getSubdomain().name().toLowerCase(), store);
}
subdomainMap = Collections.unmodifiableMap(smap);
}
public static CountryStore fromSubdomain(String subdomain) {
return subdomain == null ? null : subdomainMap.get(subdomain.toLowerCase());
}
}
</pre>Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-82996171779137423982015-09-18T19:14:00.003-07:002015-09-18T19:14:21.599-07:00Programación Reactiva: Reactive Extensions Library o RX (comenzado a aprender esta cosa de Reactive)<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/dwP1TNXE6fc/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/dwP1TNXE6fc?feature=player_embedded" width="320"></iframe></div>
<br />
<br />
<div style="text-align: justify;">
Encontré un buen video explicando la programación reactiva en el sabor de la librería
<a href="http://reactivex.io/">Reactive Extensions</a> hecho por Jafar Husain (Líder técnico en
Netflix) .
Aquí un pequeño resumen de los principales conceptos que extraje.
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://i.ytimg.com/vi/hLYMD6R6PvU/hqdefault.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img alt="Event Reacting" border="0" src="http://i.ytimg.com/vi/hLYMD6R6PvU/hqdefault.jpg" height="240" title="Event Reacting" width="320" /></a></div>
<div style="text-align: justify;">
El término reactivo se puede asociar por analogía con alguien tirando un montón de bolas hacia uno
al mismo tiempo. Tienes que reaccionar rápidamente para tratar de atraparlas todas. Uno no tiene control sobre cuándo quiere
que las pelotas sean lanzadas, sólo hay que estar preparado para la captura de ellas.
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Para empezar a entender Rx (Reactive Extensions), necesitamos tener en mente dos patrones
fundamentales de diseño en consideración: <b>Iterador</b> y <b>Observador</b>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
En Java tenemos la interfaz <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/Iterable.html">Iterable</a>, que es una interfaz que
cualquier tipo de colección puede implementar para permitir a los consumidores de esa colección obtener objetos uno a la vez. Así es como en Java
podemos utilizar el operador <b>foreach</b> para recorrer una colección. Debido a que la interfaz proporciona un específico <a href="http://docs.oracle.com/javase/7/docs/api/java/util/Iterator.html">Iterator</a> para el tipo de datos que estamos consumiendo
en la colección.<br />
<br />
Tres cosas pueden pasar cuando usamos un iterador:</div>
<ol>
<li>Obtener el siguiente item</li>
<li>No hay más
items para consumir (fin del flujo de datos)</li>
<li>Un error sucedió (en Java mediante el uso de excepciones)</li>
</ol>
<div style="text-align: justify;">
El patrón Obervador es otro famoso patrón de diseño donde subscriptores se subscriben a ciertos temas para poder ser
notificados cuando un cambio ocurre. Si analizamos este patrón encontramos que es muy similar al patrón Iterador
en el sentido que existe un productor y un consumidor; la principal diferencia es que en el Observador el productor
está en control de cuando enviar los datos, mientras que en el Iterador el consumidor es el que está en control. El
es el que decide cuando tomar los datos del productor.</div>
<div>
<br /></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZT6c1rMt7Xe5ipV0bMb1cHcS9X_RqjT6muHvHUqrekJaL8sdpYiyw_dR3nIJsMxWQ5nZquqWj5TqIcG_uiHJ-A0vYv-M0eBaumvER4IkR-yyV-pah_rm2XoRJwR1j54LZ4ykViVNcec8/s1600/fusion-iterator-observer.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em; text-align: justify;"><img alt="Iteratot Observer Fusion" border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZT6c1rMt7Xe5ipV0bMb1cHcS9X_RqjT6muHvHUqrekJaL8sdpYiyw_dR3nIJsMxWQ5nZquqWj5TqIcG_uiHJ-A0vYv-M0eBaumvER4IkR-yyV-pah_rm2XoRJwR1j54LZ4ykViVNcec8/s320/fusion-iterator-observer.png" title="Iteratot Observer Fusion" width="320" /></a><br />
<div style="text-align: justify;">
Pero hay dos aspectos principales "ausentes" del patrón Observador que si están presentes en el patrón Iterador:</div>
</div>
<div>
<ul>
<li style="align: justify;">Una manera de indicar que no hay más datos</li>
<li style="text-align: justify;">Una manera de indicar
que un error acaba de suceder</li>
</ul>
<div style="text-align: justify;">
En el Observador uno solamente puede subscribir un callback para recibir datos, pero no puede registrar callbacks
para el evento donde se indica que no hay más datos siendo encolados en el stream (evento de completado), o para
indicar que un error sucedió. RX trata básicamente de unificar el "acueducto" del Observador con el "acueducto" del Iterador
produciendo un nuevo tipo llamado el Observable, el cual proporciona la misma semántica de ambos patrones.
</div>
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Hay un montón de operaciones interesantes que se pueden realizar sobre los iterables. En SQL existen un gran número de operaciones que se pueden hacer sobre conjunto de datos: filtrar, seleccionar, ordenar,
etc. Que tal si todas esas mismas operaciones que podemos ejecutar sobre datos alojados en una tabla, pudiéramos también
hacerlo sobre eventos (datos que llegan). Eso no es una fantasía con RX. Es posible escribir sentencias al estilo SQL
sobre eventos. La diferencia es que la consulta es evaluada conforme llegan los datos. Uno puede evaluar datos en
tiempo real. </div>
<div style="text-align: justify;">
<br /></div>
<div>
<div style="text-align: justify;">
Cada vez más el código se esta volviendo orientado a eventos. Tenemos un montón de llamadas asincrónicas en el lado
del cliente (JS), y del lado del servidor (Node.JS). Esto agrega mucha complejidad en la aplicación que intenta
manejar todos estos callbacks. RX provee el nuevo tipo de datos <b>Observable</b>
para establecer una manera poderosa de modelar eventos. Al completar las semánticas faltantes (fin de flujo de datos y
error), ahora uno puede aplicar operaciones familiares que hacemos sobre colecciones como map, filter, reduce, merge, zip, etc.
Todas estas cosas podemos hacerlas sobre flujo de datos también.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Imaginemos la nueva <a href="https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html">Java 8 Stream API </a> sobre datos que llegan dinámicamente por eventos lanzados hacia uno.
Muchas cosas pueden mejorar en la aplicación como enviar datos al consumidor mucho más rápido, por citar solo
un ejemplo.
<br />
<br />
Aún necesito aprender mucho más de este nuevo paradigma, pero al menos pienso que este video cubre los conceptos fundamentales que necesitamos
tener de antemano antes de arrojarnos a jugar con RX en el código.
</div>
</div>
Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-11430820256825345372015-06-24T14:06:00.000-07:002015-06-24T14:09:22.521-07:00¿Es esto arquitectura?<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK6nuPBvERn_FKvs0L3O447xUH32lko5ldJgLm6go1dVJdcp_p3mibISWEk_YqapBTkXc-CZWXnien9_G0oahH_RbQy7bOhtU7RB19COOzcvWG98ln9sA1ZX0OmXm1C6HHClo6a8eFM3H3/s1600/arquitectura.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="186" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK6nuPBvERn_FKvs0L3O447xUH32lko5ldJgLm6go1dVJdcp_p3mibISWEk_YqapBTkXc-CZWXnien9_G0oahH_RbQy7bOhtU7RB19COOzcvWG98ln9sA1ZX0OmXm1C6HHClo6a8eFM3H3/s320/arquitectura.png" width="320" /></a></div>
<br />
<div style="text-align: justify;">
Interesante <a href="http://www.enterpriseintegrationpatterns.com/ramblings/86_isthisarchitecture.html" target="_blank">artículo de Gregor Hohpe</a> que nos enseña por analogía lo que una documentación de una arquitectura de Software debería contener. Muy resumidamente, una descripción de arquitectura de Software debería mostrar decisiones no triviales u obvias hechas en un sistema. Por ejemplo, describir que en el sistema hay una separación de capa de presentación (Front-End) con la capa de datos (Back-End), es lo mismo que decir que en una casa tenemos puertas que tocan el piso para que la gente pueda caminar por ellas.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Quizás determinar que es trivial y qué no lo es puede despertar sospechas de que estamos en terreno de lo subjetivo, pero creo que a como maduramos como desarrolladores de software, y vamos obteniendo experiencia observando patrones recurrentes en los diseños de sistemas en los que participamos, se va volviendo un poco más claro cuando algo es digno de ser documentado. Esto se nota también en el plano del código de programación cuando intentamos que el mismo sea auto-descriptivo y solo comentamos lo que no parece obvio de entender.</div>
Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-74578872450645523882015-06-05T15:07:00.001-07:002015-06-05T15:08:36.579-07:00Apache2: Configurar una página local con Host personalizado/customizado (Virtual Host)1. Crear la carpeta /wwww/domain<br />
<span style="font-family: Courier New, Courier, monospace;">sudo mkdir -p /www/domain </span><br />
<br />
2. Cambiar permisos<br />
<span style="font-family: Courier New, Courier, monospace;">sudo chown 755 /www/domain
sudo chown -R www-data:www-data /www/domain </span><br />
<br />
3. Editar Apache2 conf<br />
<span style="font-family: Courier New, Courier, monospace;">sudo gedit /etc/apache2/apache2.conf
Agregar estas líneas:
</span><br />
<pre class="brush:xml"><VirtualHost *:80>
# This first-listed virtual host is also the default for *:80
ServerName gabo.com
ServerAlias gabo.com
DocumentRoot /www/domain
</VirtualHost>
<Directory /www/domain/>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
</pre>
<br />
4. Agregar una entrada en /etc/hosts<br />
<span style="font-family: Courier New, Courier, monospace;">127.0.0.1 gabo.com </span><br />
<br />
5. Create el archivo html para prueba<br />
<span style="font-family: Courier New, Courier, monospace;">touch /wwww/domain/index.html
Con cualquier código HTML:
</span><br />
<pre class="brush:html"><http>
<body>
<h1>Hello!</h1>
</body>
</http>
</pre>
<br />
6. Abrir dominio gabo.com en el navegador.Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-60913423649672831892014-12-12T14:09:00.000-08:002014-12-12T14:09:03.814-08:00Spring Web: Obtener request actual y generar URL de la aplicación<div style="text-align: justify;">
Una forma sencilla de generar el URL base acorde con el contexto de ambiente de la aplicacion a partir del objeto request:</div>
<br />
<pre class="brush:java">protected static String getBaseEnvLinkURL() {
String baseEnvLinkURL=null;
HttpServletRequest currentRequest =
((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
baseEnvLinkURL = "http://" + currentRequest.getLocalName(); // lazy about determining protocol
if(currentRequest.getLocalPort() != 80) {
baseEnvLinkURL += ":" + currentRequest.getLocalPort();
}
if(!StringUtils.isEmpty(currentRequest.getContextPath())) {
baseEnvLinkURL += currentRequest.getContextPath();
}
return baseEnvLinkURL;
}
</pre>
Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-20403634339169728332014-11-13T12:45:00.000-08:002014-11-13T12:45:06.929-08:00Ubuntu: Resolviendo problema de instalación con aptitudeTratando de instalar el reproducto VLC en mi Ubuntu Linux 14 me daba este error usando el comando:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"><i>sudo apt-get install vlc</i></span><br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">Some packages could not be installed. This may mean that you have</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">requested an impossible situation or if you are using the unstable</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">distribution that some required packages have not yet been created</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">or been moved out of Incoming.</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">The following information may help to resolve the situation:</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">The following packages have unmet dependencies:</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> vlc : Depends: vlc-nox (= 2.2.0~rc1-1ppa1~trusty) but it is not going to be installed</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> Depends: libavcodec56 (>= 7:2.4~) but it is not going to be installed</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> Recommends: vlc-plugin-notify (= 2.2.0~rc1-1ppa1~trusty) but it is not going to be installed</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> Recommends: vlc-plugin-samba (= 2.2.0~rc1-1ppa1~trusty) but it is not going to be installed</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">E: Unable to correct problems, you have held broken packages.</span><br />
<div>
<br /></div>
<br />
Después de intentar muchos comandos para limpiar los paquetes quebrados, finalmente instalé <b>aptitude</b> y corrí el comando:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"><i>sudo aptitude install vlc</i></span><br />
<br />
Y listo, todos mis problemas de paquetes los resolvió aptitude y pude instalar mi reproductor favorito.Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-80071128848374582002014-11-04T12:03:00.001-08:002014-11-04T12:03:05.773-08:00Herramienta para captura y edición de capturas de pantalla (screenshots)<div style="text-align: justify;">
Tenía la necesidad de agregar unas flechas a unas capturas de pantalla usando mi Ubuntu. Intenté hacerlo con Gimp pero resultó más complicado de lo que pensaba. Así que instalé está recomendación: <a href="http://shutter-project.org/">http://shutter-project.org/</a>.</div>
<br />
Se puede instalar con el comando: <span style="background-color: #eeeeee; color: #222222; font-family: 'Ubuntu Mono', 'Ubuntu Beta Mono A', Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace; font-size: 14px; line-height: 18.2000007629395px; white-space: pre-wrap;">sudo apt-get install shutter</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGlS6BgCeeq000qdwqijnw1dUtaVnWS0wQUVkh5GsZF1LTCfcFgPAu9WCGcaviqpazUTW-0ssjXoggFWWgcv1WPfwe8pwqoBcDBBMW1bjT1Sgv845O-iepU9WIp4Tz1OHuF8gMK9u7qr54/s1600/shutter.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGlS6BgCeeq000qdwqijnw1dUtaVnWS0wQUVkh5GsZF1LTCfcFgPAu9WCGcaviqpazUTW-0ssjXoggFWWgcv1WPfwe8pwqoBcDBBMW1bjT1Sgv845O-iepU9WIp4Tz1OHuF8gMK9u7qr54/s1600/shutter.png" height="218" width="400" /></a></div>
<br />Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-46503162448366291332014-09-09T11:04:00.003-07:002014-09-09T11:06:06.869-07:00ORA-28002: the password will expire within X days<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Para un ambiente de desarrollo normalmente no es importante que las contraseñas de base de datos expiren. Me estaba dando ese mensaje de que mi contraseña para el usuario 'system' iba a expirar. Así que para evitar esto en el futuro y dejar la misma contraseña, ejecuté los siguientes comandos:</div>
<br />
<pre>SQL> ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED;
SQL> ALTER USER SYSTEM IDENTIFIED BY <password>;
</password></pre>Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-23552168241724362812014-06-03T10:55:00.005-07:002017-04-18T16:00:46.871-07:00GREP tips<br />
Solamente coleccionando magia grep<br />
<br />
<br />
<b>Busque ocurrencia de manera recursiva en el directorio actual, ignorando mayúsculas/minúsculas (case) y cuente el número de líneas.</b><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">grep -Ri "search_term" . | wc -l</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<br />
<b>Agrupa las ocurrencias de un path en el web-access log y cuenta las ocurrencias.</b><br />
<br />
<span style="font-family: Courier New, Courier, monospace;">grep -Eo "/wrapper-app-api(/\w+/\S*)" web-access.log | sort | uniq -c</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">3056 /wrapper-app-api/internal/graphitedump</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 146635 /wrapper-app-api/internal/health.check</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 152045 /wrapper-app-api/wrapper/community</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 27183 /wrapper-app-api/wrapper/csrf</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 37473 /wrapper-app-api/wrapper/get</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 134 /wrapper-app-api/wrapper/left/all-writers</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 1 /wrapper-app-api/wrapper/left/exercises</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 4 /wrapper-app-api/wrapper/left/food-and-recipes</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 2 /wrapper-app-api/wrapper/left/gethinmusclenutrition</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 2 /wrapper-app-api/wrapper/left/Mind</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 2 /wrapper-app-api/wrapper/left/Nutrition</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 11 /wrapper-app-api/wrapper/left/root</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 7 /wrapper-app-api/wrapper/left/Supplements</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 135 /wrapper-app-api/wrapper/left/Training_Main</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 204 /wrapper-app-api/wrapper/locale</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 35 /wrapper-app-api/wrapper/notstore</span><br />
<span style="font-family: Courier New, Courier, monospace;"></span><br />
<span style="font-family: Courier New, Courier, monospace;"> 593 /wrapper-app-api/wrapper/proxy.html</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"><br /></span>Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-38892255503615986462014-04-15T12:44:00.002-07:002014-04-15T12:45:17.247-07:00Java: URL de archivo localizado en el classpath<br />
Una manera de averiguar el URL de un archivo localizado en el classpth (útil en casos como tests de unidad de classes que consumen datos por la web):<br />
<br />
<pre class="brush: java">getClass().getClassLoader();
String url = ClassLoader.getSystemResource("path/to/file").toString();
</pre>
Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-84407854620206138862014-04-09T10:19:00.004-07:002014-04-09T10:20:22.082-07:00Eclipse Maven: 'Updating Maven Project' has encountered a problem. <div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfhrBFFBgN_zc3-wPKQmVEvtoYCOwYXS8SWd11kjS5ZLt506G_HPoKjoU9WB33MW9i4TaKAjvG4L6nkd7uQHaKjlvW_TWpNS82GEWnYvfe_0OG6l1CsMxYAma3n2xc10uJk9gwdBL4KBQZ/s1600/maven-update-project-error.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfhrBFFBgN_zc3-wPKQmVEvtoYCOwYXS8SWd11kjS5ZLt506G_HPoKjoU9WB33MW9i4TaKAjvG4L6nkd7uQHaKjlvW_TWpNS82GEWnYvfe_0OG6l1CsMxYAma3n2xc10uJk9gwdBL4KBQZ/s1600/maven-update-project-error.png" height="172" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<span style="font-family: Courier New, Courier, monospace;">'Updating Maven Project' has encountered a problem. </span><br />
<span style="font-family: Courier New, Courier, monospace;">An internal error ocurred during 'Updating Maven project'.</span><br />
<span style="font-family: Courier New, Courier, monospace;">java.lang.NullPointerException</span><br />
<br />
De repente comencé a tener este error con uno de mis proyectos de Maven. La mejor solución que encontré fue:<br />
<br />
<br />
<ol>
<li>Borrar el proyecto de Eclipse (no los archivos)</li>
<li>Borrar el .project y el .settings/ del proyecto</li>
<li>Re imporar el proyecto</li>
<li>Convertirlo a un proyecto Maven </li>
</ol>
Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-83354837925901078172014-03-18T15:46:00.003-07:002016-03-16T10:00:46.583-07:00MongoDB Tips<br />
<h4>
Actualizar todos los documentos de una colección para agregar un nuevo campo:</h4>
<span style="font-family: "courier new" , "courier" , monospace;">db.<COLLECTION>.update({}, {$set: {<NEW_FIELD>:<VALUE>} }, {multi:true})</span><br />
<br />
<h4>
Renombrar el nombre de una columna/campo</h4>
<span style="font-family: "courier new" , "courier" , monospace;">db.<COLLECTION>.update({}, {$rename: {'<OLD_FIELD_NAME>': '<NEW_FIELD_NAME>'}}, false, true);</span><br />
<h4>
Exportar/Importar una colección</h4>
<span style="font-family: "courier new" , "courier" , monospace;">
mongoexport -d <DATABASE> -c <COLLECTION> -o <FILE_PATH> <br />
mongoimport -d <DATABASE> -c <COLLECTION> --file <FILE_PATH>
</span><br />
<h4>
Remover una columna/atributo en todos los documentos de la colección</h4>
<span style="font-family: "courier new" , "courier" , monospace;">db.<COLLECTION>.update({}, {$unset: {<FIELD>:""} }, {multi:true})</span><br />
<br />
<h4>
Consultar todos los documentos donde un arreglo tiene tamaño mayor a 0</h4>
<span style="font-family: "courier new" , "courier" , monospace;">db.<COLLECTION>.find({ $where: "this.FIELD.length > 1" } )</span><br />
<br />
<h4>
Consultar por tamaño de un arreglo mayor a n
</h4>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">db.getCollection(<COLLECTION>).find({ $where: "this.<ARRAY_FIELD>.length > 8" })</span></div>Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-39697970074947019322014-03-14T13:47:00.004-07:002014-03-14T13:47:50.634-07:00Log4j: Tips<h4>
Cambiar el nivel de log para un paquete o clase </h4>
En el log4j.properties:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">log4j.rootLogger=INFO,Stdout</span><br />
<span style="font-family: Courier New, Courier, monospace;">log4j.logger.<put>.<package>.<path>.<here>=DEBUG</here></path></package></put></span>Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-37484673577341408582014-03-14T13:27:00.002-07:002014-03-14T13:28:48.870-07:00SLF4J: Multiple bindings were found on the class path logback<div style="text-align: justify;">
En el proyecto que estoy trabajando utilizamos <a href="http://www.slf4j.org/" target="_blank">SLF4J </a>como framework de logging. Estaba teniendo un problema en el cual mis llamados para registrar entradas en el log no estaban apareciendo. Al principio pensé que era un problema con el archivo de log4j ya que esta era la implentación final que se estaba utilizando. Sin embargo luego me dí cuenta de unos mensajes apareciendo al principio del arranque de la aplicación:</div>
<br />
<span style="color: red; font-family: Courier New, Courier, monospace;">SLF4J: Class path contains multiple SLF4J bindings.</span><br />
<span style="color: red; font-family: Courier New, Courier, monospace;">SLF4J: Found binding in [jar:file:/home/atg-dev/.m2/repository/ch/qos/logback/logback-classic/0.9.28/logback-classic-0.9.28.jar!/org/slf4j/impl/StaticLoggerBinder.class]</span><br />
<span style="color: red; font-family: Courier New, Courier, monospace;">SLF4J: Found binding in [jar:file:/home/atg-dev/.m2/repository/org/slf4j/slf4j-log4j12/1.6.2/slf4j-log4j12-1.6.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]</span><br />
<span style="color: red; font-family: Courier New, Courier, monospace;">SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.</span><br />
<span style="color: red; font-family: Courier New, Courier, monospace;">2014-03-13 21:30:46.718:INFO:/search-indexer:Initializing Spring root WebApplicationContext</span><br />
<br />
<br />
<div style="text-align: justify;">
Los mensajes estaban indicando que habían varios bindings, es decir, varias implementaciones de logging dentro del classpath. En específico pude ver que aparte de Log4j estaba LogBack, el cual no encontré ninguna referencia en el pom.xml. Había que descubrir la dependencia indirecta/transitiva.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
La mejor manera para hallar la dependencia transitiva fue una idea de un compañero de utilizar el plugin de Maven en Eclipse que permite ver la jerarquía de dependencias.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgygAuUVWStfULsjiBiLHR2LWHRGrkTkVU-CQpNH_ZUbeltAhCBgjlN8dj9DgJ6I-qBtE_jUp4VjxVQNAEatR68AG9ngu2BbcnIf_ARPS-vo3hIxt1bwH0Z2xZV93Y6cmIuYCe6mCw-P2Uc/s1600/pom-dependencies.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgygAuUVWStfULsjiBiLHR2LWHRGrkTkVU-CQpNH_ZUbeltAhCBgjlN8dj9DgJ6I-qBtE_jUp4VjxVQNAEatR68AG9ngu2BbcnIf_ARPS-vo3hIxt1bwH0Z2xZV93Y6cmIuYCe6mCw-P2Uc/s1600/pom-dependencies.png" height="304" width="320" /></a></div>
<br />
<br />
<div style="text-align: justify;">
De esa manera pude ubicar la dependencia que incluía al logback y agregar la exclusión:</div>
<br />
<br />
<br />
<pre class="brush:xml"> <dependency>
<groupId>com.xxx.content</groupId>
<artifactId>content-dao-jar</artifactId>
<version>xx.xx.x.x</version>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
</pre>
Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-1843325211851242232014-03-11T07:47:00.000-07:002014-12-10T13:48:02.974-08:00Git: Lista de comandos útiles<h4>
Revertir cambios locales del branch al contenido remoto</h4>
<span style="font-family: Courier New, Courier, monospace;">git reset --hard origin/<branch></span><br />
<h4>
<span style="font-family: Times, Times New Roman, serif;">Fusionar branch2 en branch1</span></h4>
<span style="font-family: Courier New, Courier, monospace;">git checkout branch1</span><br />
<span style="font-family: Courier New, Courier, monospace;">git merge branch2</span>
<br />
<h4>
<span style="font-family: Times, Times New Roman, serif;">Enviar un branch local al servidor remoto</span></h4>
<span style="font-family: Courier New, Courier, monospace;">git push origin branc</span>
<br />
<h4>
<span style="font-family: Times, Times New Roman, serif;">Mostrar branches locales</span></h4>
<span style="font-family: Courier New, Courier, monospace;">git branch</span><br />
<br />
<h4>
Borrar branch remoto</h4>
<div>
<span style="font-family: Courier New, Courier, monospace;">git push origin --delete branchname</span></div>
<h4>
Borrar branch local</h4>
<div>
<span style="font-family: Courier New, Courier, monospace;">git branch -D the_local_branch</span></div>Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-41799840774959210222014-03-06T09:14:00.000-08:002014-03-06T09:14:57.834-08:00JMeter: Primeros pasos probando rendimiento de aplicaciones web<div style="text-align: justify;">
Una gran herramienta en la caja de herramientas de todo buen desarrollador de software, es aquella que te permite evaluar el rendimiento de una aplicación. En el caso de aplicaciones web es extremadamente necesario hacer estas pruebas de rendimiento simulando una alta concurrencia de usuarios debido a la naturaleza concurrente de la web.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Una gran herramienta open source para realizar este tipo de pruebas se llama <a href="http://jmeter.apache.org/" target="_blank">JMeter de Apache</a>. Con ella puedo crear múltiples solicitudes a una dirección web y medir la respuesta para examinar el compartamiento en términos de rendimiento.</div>
<br />
<br />
<div style="text-align: center;">
<img alt="Apache JMeter" src="http://jmeter.apache.org/images/logo.jpg" /></div>
<br />
Pasos para crear un plan de pruebas sencillo:<br />
<br />
<br />
<ol>
<li>Descargar JMeter del <a href="http://jmeter.apache.org/" target="_blank">sitio web oficial de Apache</a>. En Ubuntu se puede instalar usando el comando: <b><i>apt-get install jmeter</i></b></li>
<li>Agregue un Thread Group al Test Plan: Clic derecho en el test plan ->Add->Threads (Users)->Thread Group<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSgFgyEr5iQCETXPc0FZDC2bMkNMtIz1K3tyYuPlU7tLiGTB9dVRwY5O9uhNvA-yKvgNqrGqrtXvHUMQiVNPHWQmAmDCtDdO30ZEwLBakvSpN59JfzV3UZ6phRwejlSGmA1kqsZb1yZWm2/s1600/thread-group.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSgFgyEr5iQCETXPc0FZDC2bMkNMtIz1K3tyYuPlU7tLiGTB9dVRwY5O9uhNvA-yKvgNqrGqrtXvHUMQiVNPHWQmAmDCtDdO30ZEwLBakvSpN59JfzV3UZ6phRwejlSGmA1kqsZb1yZWm2/s1600/thread-group.png" /></a></div>
</li>
<li>Edite los campos del Thread Group como el número de usuarios y la cantidad de ciclos, entre otros.<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2MnNlO8K-2K-d2nwRzrjLKzJvtp2PB1fu9fIusnvtrbNEFThWSvVL1gnIE3e6tWjTnazukq_ctr3JFM7sD49Sb4zBzZ9PCt2f9yDTZQLvHiXTVO5ABcROByMcinuOTm-pTdCn2gh76iGT/s1600/thread-group-edit.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2MnNlO8K-2K-d2nwRzrjLKzJvtp2PB1fu9fIusnvtrbNEFThWSvVL1gnIE3e6tWjTnazukq_ctr3JFM7sD49Sb4zBzZ9PCt2f9yDTZQLvHiXTVO5ABcROByMcinuOTm-pTdCn2gh76iGT/s1600/thread-group-edit.png" height="113" width="400" /></a></div>
</li>
<li>Agregamos un HTTP Request: Clic derecho en el Thread Group->Add->Sampler->HTTP Request</li>
<li>Editamos los campos requeridos de acuerdo al tipo de request<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiE91y54YafCJbdjeiq6wJ3anOzsocPxhxfoQEx-vQNbXLVd-6OK0gor0Va8KzHf3himWh10NLLyJCBGK5otq9DEQlqxf0VGepgHZE5jfuZ2C_R5QQxLxc5rOV5yR3eAHYg7wJmXWO0Ob8Q/s1600/httprequest.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiE91y54YafCJbdjeiq6wJ3anOzsocPxhxfoQEx-vQNbXLVd-6OK0gor0Va8KzHf3himWh10NLLyJCBGK5otq9DEQlqxf0VGepgHZE5jfuZ2C_R5QQxLxc5rOV5yR3eAHYg7wJmXWO0Ob8Q/s1600/httprequest.png" height="195" width="400" /></a></div>
</li>
<li>Agregamos un listener de acuerdo al tipo de reporte que desemos: Clic derecho en Test Plan->Add->Listener->Graph Results</li>
<li>Damos Start y observamos nuestro gráfico crecer<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZLIfdzRlBMuzjydB9Jnc2gLpCgsh8A6g-E3SxhOD8LrPpJfWq7wKjQu_fgAiKCaJiAvRWQ7EjyL4q-p9RIxTLARjqXsBevNQRaNob-Z4EjZ_Qy4hlGLw-Q4u7a5XFNVTxuYD2FShwCsNh/s1600/start.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZLIfdzRlBMuzjydB9Jnc2gLpCgsh8A6g-E3SxhOD8LrPpJfWq7wKjQu_fgAiKCaJiAvRWQ7EjyL4q-p9RIxTLARjqXsBevNQRaNob-Z4EjZ_Qy4hlGLw-Q4u7a5XFNVTxuYD2FShwCsNh/s1600/start.png" height="135" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx4wZe7N8WTyLVIThaCjhYLxgdK60IuXHpeGyIij_OoaUk5AFrPsGg1h3Xdzzz1ZhSCpiy76gyWKGLJ_68hGSDcgcj9x7N7OqOR0eHJU2mLJ-goeCny1WIHMTvkjeKJFdd1k8tAIN_mpUN/s1600/graph.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx4wZe7N8WTyLVIThaCjhYLxgdK60IuXHpeGyIij_OoaUk5AFrPsGg1h3Xdzzz1ZhSCpiy76gyWKGLJ_68hGSDcgcj9x7N7OqOR0eHJU2mLJ-goeCny1WIHMTvkjeKJFdd1k8tAIN_mpUN/s1600/graph.png" height="240" width="400" /></a></div>
</li>
<li>Interpretamos los resultados y/o ajustamos el plan para obtener la información que requerimos</li>
</ol>
Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-40476511966459844012014-02-12T20:59:00.002-08:002014-02-12T21:02:55.409-08:00Tridion y sus bloques de construcción<br />
<br />
<div style="text-align: justify;">
Siempre es bueno guardar conceptos claves de las tecnologías que uno ha usado en el pasado. El aprender a reconocer debilidades y fortalezas de una tecnología es vital para desarrollar un criterio ingenieril o arquitectural que nos ayuda a tomar mejores decisiones técnicas.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Hace un tiempo trabajé con un administrador de contenido propietario llamado <a href="http://www.sdl.com/" target="_blank">Tridion de SDL</a>. Sinceramente no me agradó mucho por algunas razones que no vienen al caso mencionar ahora, pero hubieron varios conceptos que me agradaron y que comentaré brevemente en algunas entradas de blog.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Unos de los conceptos que me llamó la atención es la manera muy clara en que separan el contenido de la presentación, y como lo hacen de una manera escalonada por medio de sus "bloques de construcción". Esta separación es sumamente importante en un buen administrador de contenido o CMS (Content Management System). Es altamente deseable que el contenido en un sistema de contenido se pueda preservar mientras su presentación evoluciona con el tiempo adaptando las nuevas tendencias de presentación web.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Esta facilidad permite también una excelente separación de roles donde tenemos editores de contenido que no se preocupan porque el contenido luzca agradable, y por otra parte los diseñadores web que maquillan el sitio web acorde a las tendencias de moda.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
En organizaciones muy grandes, esta característica permite además imponer una serie de formatos, y/o plantillas para mantener uniformidad en sitios (o gama de sitios) web grandes y complejos donde muchas personas editan contenido.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
La manera en que lo hace Tridion es definiendo los siguientes bloques de construcción de páginas web.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Los <b><span style="font-size: large;">esquemas</span></b> (schemas) definen los metadatos de un componente como lo son los nombres de los campos, sus tipos y si son mandatorios o no. En el ejemplo graficado abajo se muestra un esquema de comida con campos como título y subtítulo de tipo texto, y imagen de tipo imagen.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Luego un <b><span style="font-size: large;">componente</span></b> (component) es como la instancia de un esquema. Es decir, llenar los campos de un esquema con valores específicos. En el ejemplo se llena el esquema de comida con datos de una pizza.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
La <b><span style="font-size: large;">plantilla del componente</span></b> (component template) viene a definir la disposición y estilos básicos de los distintos campos del componente. Un componente podría disponer de diferentes plantillas de acuerdo a las distintas necesidades de presentación. Por ejemplo, en el gráfico se muestra una alineación hacia la derecha de la imagen de la comida con el título y subtítulo encabezando a la izquierda, seguidamente del cuerpo del texto. Uno podría disponer otra plantilla que quizás se utilice para resultados de búsquedas donde la imagen se omite y solo se muestra el título con el texto de la descripción de la comida truncado.</div>
<br />
<div style="text-align: justify;">
La <span style="font-size: large;"><b>plantilla de la página</b> </span>(page template) establece los elementos globales de una plantilla web particula. Típicos casos de menús de navegación, encabezados, pies de página, etc.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
La <b><span style="font-size: large;">presentación del componente</span></b> (component presentation) es la unión de un componente particular con una plantilla de componente. El resultado final es la presentación del contenido del componente en su forma agradable para el usuario.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Finalmente cuando se une la plantilla de la página con uno o más componentes de presentación tenemos finalmente una <b><span style="font-size: large;">página web</span></b> (web page).</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-pgniSDziGUP5vG59vcn4dIU-UnW_zHNnmQMS2aLZWgqwymzW2wBLWtkwDlw_KwRB5-NBStnfMnUGTwzb5ZkiAJDOOMKEMGy-bJ6yKzizxtE-PYOj6XRXDuOeUR3aIgJfrGRy_2Gpo7vk/s1600/tridion-building-blocks.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-pgniSDziGUP5vG59vcn4dIU-UnW_zHNnmQMS2aLZWgqwymzW2wBLWtkwDlw_KwRB5-NBStnfMnUGTwzb5ZkiAJDOOMKEMGy-bJ6yKzizxtE-PYOj6XRXDuOeUR3aIgJfrGRy_2Gpo7vk/s1600/tridion-building-blocks.png" height="417" width="640" /></a></div>
<div style="text-align: justify;">
<br />
<span style="text-align: left;">Sin duda esta separación de contenido y presentación implica mucho trabajo al inicio con la definición de esquemas, plantillas y componentes, pero la retribución final es satisfactoria al explotar la gran flexibilidad que se alcanza con este modelo.</span></div>
Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-71875731577381576732013-11-08T13:38:00.000-08:002013-11-08T13:38:13.450-08:00Ubuntu: Creando y reintegrando un archivo tar multi-partes<div style="text-align: justify;">
Necesitaba guardar una máquina virtual en mi disco duro externo y me di cuenta que lo tenía formateado en FAT32, por lo cual no podía guardar un archivo mayor a 4GB.</div>
<div style="text-align: justify;">
<br /></div>
Así que indague la manera de crear un archivo tar multi partes:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">tar -cvf - myVM.vdi | split --bytes=4000m --suffix-length=4 --numeric-suffix - MyVM.tar.</span><br />
<br />
Para reintegrarlo:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">cat MyVM.tar.* | tar xvf -</span><br />
<br />
<br />
<br />Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-55520870879538127662013-11-06T06:39:00.002-08:002013-11-06T06:39:49.540-08:00ATG Colorizer: libstdc++.so.6: cannot open shared object file: No such file or directory<pre class="lang-c prettyprint prettyprinted">Estaba en medio de mi configuración inicial de desarrollo de ATG y comenzé a tener problemas con una pequeña aplicación llamada ATG Colorizer.</pre>
<pre class="lang-c prettyprint prettyprinted">
</pre>
<pre class="lang-c prettyprint prettyprinted">Me daba el siguiente error:</pre>
<pre class="lang-c prettyprint prettyprinted"><span style="font-family: Courier New, Courier, monospace;">libstdc++.so.6: cannot open shared object file: No such file or directory</span></pre>
<pre class="lang-c prettyprint prettyprinted">
</pre>
<pre class="lang-c prettyprint prettyprinted">Intenté instalar la librería como lo había hecho antes, pero parecía que mi nuevaversión de Ubuntu no reconocía la receta antigua de instalación.</pre>
<pre class="lang-c prettyprint prettyprinted">
</pre>
<pre class="lang-c prettyprint prettyprinted">Así que después de buzear un rato por Internet encontré una manera que sí le gustó a mi Ubuntu:</pre>
<pre class="lang-c prettyprint prettyprinted"><code><span class="pln"> </span></code></pre>
<pre class="lang-c prettyprint prettyprinted"><code><b><span style="font-family: Courier New, Courier, monospace;"><span class="pln">apt</span><span class="pun">-</span><span class="pln">get install lib32stdc</span><span class="pun">++</span></span></b><span class="lit" style="font-family: Courier New, Courier, monospace;"><b>6</b></span></code></pre>
Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-7320747093334447432013-10-16T15:37:00.002-07:002013-10-16T15:37:38.572-07:00Escribiendo imagen ISO de Ubuntu en USBComando para escribir una imagen (iso) booteable de Ubuntu a una llave USB:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">sudo dd if=ubuntu-13.04-desktop-amd64.iso of=/dev/sdb oflag=direct bs=1048576</span><br />
<br />
En mi caso el dispositivo USB se montaba en /dev/sdb. Para chequar los mounts del sistema se puede ejecutar el siguiente comando:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">sudo fdisk -l</span>Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-67750024458252527452013-09-10T10:17:00.001-07:002013-09-10T10:17:20.351-07:00ATG: Template Error: category error 2<br />
Comencé a tener este problema después de un merge de código. Todavía no sé por qué sucedió, pero estaba impidiendo mi trabajo.<br />
<br />
El error sucedía en el droplet: /atg/commerce/catalog/CategoryLookup. Encendí el debug para obtener más información:<br />
<br />
<pre>14:01:43,960 INFO [CategoryLookup] DEBUG Find item: id=BRAND_OPTIMUM; type=category
14:01:43,961 INFO [CategoryLookup] DEBUG Item Found:category:BRAND_OPTIMUM
14:01:43,961 INFO [CategoryLookup] DEBUG Is item in catalog catalog:masterCatalog
14:01:43,961 INFO [CategoryLookup] DEBUG This item is not in the correct catalog.
</pre>
<br />
Un colega experto en ATG me ayudó mostrandome una página de mantenimiento en Dyn Admin que se utilizar para solucionar este tipo de errores:<br />
<br />
<h2 style="color: #00214a;">
Basic Catalog Maintenance</h2>
<a href="http://localhost:8080/dyn/admin/atg/commerce/admin/en/maintenance/startService.jhtml?process=BasicMaintProcess">http://localhost:8080/dyn/admin/atg/commerce/admin/en/maintenance/startService.jhtml?process=BasicMaintProcess</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3WIZBCnvzt-Bh0G3xZox0J3e43UesbiRaReMj4SPn7Iblyw-Rwlc0qB8AqHiNVTPNZzzYy2SbCXe_utylO3HcRhiF44IVlBDLWOKSIdlVaOSuSu6VLa7zWC08VUpsRxMwPB0kjCwLiAM/s1600/atg-basic-catalog-maintenance.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="151" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3WIZBCnvzt-Bh0G3xZox0J3e43UesbiRaReMj4SPn7Iblyw-Rwlc0qB8AqHiNVTPNZzzYy2SbCXe_utylO3HcRhiF44IVlBDLWOKSIdlVaOSuSu6VLa7zWC08VUpsRxMwPB0kjCwLiAM/s400/atg-basic-catalog-maintenance.jpg" width="400" /></a></div>
<br />
Así que solo corrí el proceso y los problemas desaparecieron.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQHrEZIdIUliUHb2msrRu6_-FMsjNm_c-CFa9tVaaP0wsZi0sp83FXKLmuOuarHgA1qiibnItaqCsT-hW3lsmrnLQJG_QQqPLkfq_IxAf2wiWCYVad2xgoJ6R2Z59-5rkzX0G8vFzKbgk/s1600/atg-catalog-maintenance-log.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="125" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQHrEZIdIUliUHb2msrRu6_-FMsjNm_c-CFa9tVaaP0wsZi0sp83FXKLmuOuarHgA1qiibnItaqCsT-hW3lsmrnLQJG_QQqPLkfq_IxAf2wiWCYVad2xgoJ6R2Z59-5rkzX0G8vFzKbgk/s400/atg-catalog-maintenance-log.jpg" width="400" /></a></div>
Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-80331248356447901272013-09-09T14:39:00.001-07:002013-09-09T14:39:28.647-07:00Flyway: No enum const class com.googlecode.flyway.core.api.MigrationState.SUCCESSEsta excepción lanzada por Flyway:<br />
<br />
<pre>java.lang.IllegalArgumentException: No enum const class com.googlecode.flyway.core.api.MigrationState.SUCCESS
at java.lang.Enum.valueOf(Enum.java:214)
at com.googlecode.flyway.core.api.MigrationState.valueOf(MigrationState.java:21)
at com.googlecode.flyway.core.metadatatable.MetaDataTable$MigrationInfoRowMapper.mapRow(MetaDataTable.java:382)
at com.googlecode.flyway.core.metadatatable.MetaDataTable$MigrationInfoRowMapper.mapRow(MetaDataTable.java:370)
at com.googlecode.flyway.core.util.jdbc.JdbcTemplate.query(JdbcTemplate.java:319)
...
</pre>
<br />
sucede por un valor inválido in la columna 'state'. En mu caso estaba fallando por un espacio en blanco extra del cual no me había dado cuenta.<br />
<br />Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-20282176415744355252013-09-06T10:29:00.000-07:002013-09-06T10:29:00.648-07:00Juniper VPN: sysdeps.error Failed to open /etc/resolv.conf with error 2 (sysdeps.cpp:715)<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYknlhugrwhngXmida-JcFpFi6NQJU3qIjh_9DICIunCe6JpzTKrbFm3sGO6zmINrrnYlKbw2JCuLDO-ANy4fwgMNxH1WfKDnUzy3eC-guCVAntiYI7Ql1FkWPXiDSQ1naV6_lGXxGndTs/s1600/network_connect.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYknlhugrwhngXmida-JcFpFi6NQJU3qIjh_9DICIunCe6JpzTKrbFm3sGO6zmINrrnYlKbw2JCuLDO-ANy4fwgMNxH1WfKDnUzy3eC-guCVAntiYI7Ql1FkWPXiDSQ1naV6_lGXxGndTs/s1600/network_connect.jpg" /></a></div>
<br />
<br />
<div style="text-align: justify;">
En mi trabajo usamos un cliente de Juniper para la conexión de VPN. De repente comenzé a tener problemas para conectarme. Al principio parece que la conexión se va a establecer pero de repente se cerraba e indicaba que la conexión se cerró satisfactoriamente.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Chequeando los logs me di cuenta de un error que se mostraba:</div>
<br />
<b>ncsvc[p10461.t10461] sysdeps.error Failed to open /etc/resolv.conf with error 2 (sysdeps.cpp:715)</b><br />
<br />
Fui a revisar el dichoso archivo /etc/resolv.conf y efectivamente no existía. Así que simplemente lo cree (en mi caso tenía un symlink quebrado). Listo problema resuelto.<br />
<br />
<br />
<br />
<br />
<br />Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com0tag:blogger.com,1999:blog-4672718424022381865.post-12549046830936306902013-08-21T15:43:00.002-07:002013-08-21T15:45:07.218-07:00Apache: Verificando errores en la configuración de VirtualHosts<div style="text-align: justify;">
<br />
Hace poco necesitaba verificar por qué una configuración de VHost no me estaban cargando. Para ello ejecuté el comando:</div>
<br />
<b><span style="font-family: Courier New, Courier, monospace; font-size: large;">apachectl -S</span></b>
<br />
<b><span style="font-size: large;"><br /></span></b>
El comando muestra cada uno los VirtualHosts que se cargan así como cualquier error de configuración:
<br />
<br />
<pre>VirtualHost configuration:
wildcard NameVirtualHosts and _default_ servers:
*:443 is a NameVirtualHost
default server www.example.com (/etc/apache2/sites-enabled/example-ssl:1)
port 443 namevhost www.exampleg.com (/etc/apache2/sites-enabled/example-ssl:1)
*:80 is a NameVirtualHost
default server example.com (/etc/apache2/sites-enabled/example:29)
</pre>
<br />
<div style="text-align: justify;">
De ahí me pude dar cuenta que mi nuevo archivo de VHost no se estaba cargando porque no es suficiente tener el archivo en /etc/apache2/sites-available, sino que hay que crear un symlink en /etc/apache2/sites-enabled.</div>
Gabriel Solanohttp://www.blogger.com/profile/15936026176587418957noreply@blogger.com1