pello.info News http://www.pello.info/index.php/rss2 pello.info News syndication 2014-04-17 10:04:33 http://www.pello.info/index.php/rss2 es Arkapong http://www.pello.info/index.php/blog/arkapong http://www.pello.info/index.php/blog/arkapong 2014-04-07 07:35:33 pelloxabier http://www.pello.info/index.php/blog/arkapong

This a classic pong-like game that takes some ideas from Arkanoid. Basically two paddles try to hit the ball until one of them fails but, from time to time the rules can change if special bricks are touched.

  • Red: invert ball direction
  • White: triple ball
  • Yellow: smaller paddles
  • Blue: bigger paddles
  • Green: speed up ball
  • Orange: change ball up-down direction
  • Brown: minimize paddles
  • Pink: move paddles randomly

For one or two players, much more fun if you play it against someone else, the game is controlled with your fingers. You can set your preferred ball speed using the preferences screen.

There is another Arkapong out there, not released yet but It looks very interesting. It's a similar concept but this one is more based on Arkanoid

]]>

This a classic pong-like game that takes some ideas from Arkanoid. Basically two paddles try to hit the ball until one of them fails but, from time to time the rules can change if special bricks are touched.

  • Red: invert ball direction
  • White: triple ball
  • Yellow: smaller paddles
  • Blue: bigger paddles
  • Green: speed up ball
  • Orange: change ball up-down direction
  • Brown: minimize paddles
  • Pink: move paddles randomly

For one or two players, much more fun if you play it against someone else, the game is controlled with your fingers. You can set your preferred ball speed using the preferences screen.

There is another Arkapong out there, not released yet but It looks very interesting. It's a similar concept but this one is more based on Arkanoid

]]>
http://www.pello.info/index.php/blog/arkapong
Getting started with Node http://www.pello.info/index.php/blog/getting-started-with-node http://www.pello.info/index.php/blog/getting-started-with-node 2014-03-17 23:48:44 pelloxabier http://www.pello.info/index.php/blog/getting-started-with-node

Few days ago, a very dear friend of mine came up to my place with a present. It was a nodejs book. This is a new or maybe it would be more accurate to say an emergent technology which brings back an old idea that I used to hear of long time ago: a server side javascript. That was something that was supposed to exist somewhere, as it was mentioned in the prefaces of many javascript related papers: “javascript runs on the browser but there is also a server side…” for me it was just a sort of legend, without any proof of real existence or running implementation. Around 2009 Ryan Dahl, based on google chrome’s V8 javascript engine, started developing a server side platform to run javascript code. NodeJS environment, basically, lead us to event-driven programming, nonblocking I/O and function callbacks.

The core of NodeJS (or simply Node) is a very simplified base where you can build your applications. But you don’t need to develop everything from scratch, Node coders are a pretty active community that already has thousands of modules of all kinds covering every aspect you can think of.

If you want to start coding and running Node programs right now you can download it from their website. In the event that you feel the need for further explanation to install Node on your computer, do yourself a favor and don’t keep on trying. I’m serious here. Stay away from any computer, run away to the countryside, pick up berries, talk to birds and you’ll live happily ever after.

¿What kind of tools can be used for node? from console based to modern IDEs. Vim, Sublime or other simple editors for example. For debugging purposes your chrome browser can be attached to a node program. Also you can use Eclipse based Nodeclipse or a nonfree IDEs like WebStorm

Last summer I played around with Node, testing callbacks, event emitters, express, MongoDB drivers, among other things... From now on I’ll try to follow this book and write stuff about Node on a regular basis. Hope that you enjoy the ride.

]]>

Few days ago, a very dear friend of mine came up to my place with a present. It was a nodejs book. This is a new or maybe it would be more accurate to say an emergent technology which brings back an old idea that I used to hear of long time ago: a server side javascript. That was something that was supposed to exist somewhere, as it was mentioned in the prefaces of many javascript related papers: “javascript runs on the browser but there is also a server side…” for me it was just a sort of legend, without any proof of real existence or running implementation. Around 2009 Ryan Dahl, based on google chrome’s V8 javascript engine, started developing a server side platform to run javascript code. NodeJS environment, basically, lead us to event-driven programming, nonblocking I/O and function callbacks.

The core of NodeJS (or simply Node) is a very simplified base where you can build your applications. But you don’t need to develop everything from scratch, Node coders are a pretty active community that already has thousands of modules of all kinds covering every aspect you can think of.

If you want to start coding and running Node programs right now you can download it from their website. In the event that you feel the need for further explanation to install Node on your computer, do yourself a favor and don’t keep on trying. I’m serious here. Stay away from any computer, run away to the countryside, pick up berries, talk to birds and you’ll live happily ever after.

¿What kind of tools can be used for node? from console based to modern IDEs. Vim, Sublime or other simple editors for example. For debugging purposes your chrome browser can be attached to a node program. Also you can use Eclipse based Nodeclipse or a nonfree IDEs like WebStorm

Last summer I played around with Node, testing callbacks, event emitters, express, MongoDB drivers, among other things... From now on I’ll try to follow this book and write stuff about Node on a regular basis. Hope that you enjoy the ride.

]]>
http://www.pello.info/index.php/blog/getting-started-with-node
Calcular el IBAN con php http://www.pello.info/index.php/blog/calcular-el-iban-con-php http://www.pello.info/index.php/blog/calcular-el-iban-con-php 2014-01-18 00:01:21 pelloxabier http://www.pello.info/index.php/blog/calcular-el-iban-con-php Los organismos internaciones se han vuelto a poner de acuerdo para poner unificar los números de cuenta y gracias a ello todos los programadores y DBAs del mundo ya estamos enfrascados en la tarea de adaptar programas, validaciones, campos de las BBDD y un largo etcétera.

En cada país el código de cuenta corriente puede variar y a través del IBAN se intenta unificar la forma de esa cuenta de tal forma que sea validable. Este artículo de la wikipedia lo explica bastante bien, incluyendo los pasos tanto para generar un IBAN a partir de una CC como para validarlo

Hay una pequeña pega, la validación exige una operación mod sobre un número tan grande que es probable que muchos lenguajes no puedan llevarla a cabo. En la red existen ya muchas soluciones, esta es una. Ojo, aparte de que este ejemplo solo se ha probado con cuentas en el formato de 20 dígitos esto no ha sido más que una diversión. Tienes implementaciones mejores como php-iban

NOTA:Para evitar problemas con el copy paste o posibles fallos con algún caracter, puedes descargarte esto del repositorio de git

<?php
/**
* Iban
* Simple utility class to generate and validate IBAN account numbers
* Based on http://www.lawebdelprogramador.com/foros/Visual_Basic/1409866-Calculo_IBAN.html
* @author Pello Xabier Altadill Izura
* @version    $Id:$
* @link       http://www.pello.info
* @since      Available since 2014-01-17
* @greetz	Iban (Zabalza)
*  ... and you too
*/

class Iban {
   
   private static $LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	private static $COUNTRIES = array("DE","EN","IT","NO","FR","PL","RO","SR","BG","SL","NL","RU","HU","LT","TR","CA","SV","ZH","EL","ES","SQ","PT","CS","FI","SK","DA","HR","LV","ET","JA","KA","MN");

   
   /**
   * Given a 20 digit account number, 
   * generates and returns IBAN account
   * needs refactoring
   */
	public static function generate ($accountNumber, $countryCode, $ibanPrefix=false,$spaces=true) {
		
		$longAccount = "";
		$remainder = 0;
		$prefix = ($ibanPrefix)?'IBAN':'';

		// Remove space chars, if any
		$accountNumber = self::clear($accountNumber);

		if (self::invalidCountryCode($countryCode)) {
			return 'Invalid country code: ' . $countryCode;
		}		
		
		if (self::invalidAccountNumber($accountNumber)) {
			return 'Invalid account Number: ' . $accountNumber;
		}
		

		$longAccount =  self::rearrangeAccount($accountNumber,$countryCode);

		$remainder = self::calculateRemainder($longAccount);

		if ($spaces) {
	   	return self::addSpaces($prefix . $countryCode . sprintf('%02d',(98-$remainder)) . $accountNumber);
	   } else {
	   	return $prefix . $countryCode . sprintf('%02d',(98-$remainder)) . $accountNumber;
	   }
	}
	
	/**
	* validates an IBAN account
	*
	*/
	public static function validate ($ibanAccount) {
		$longAccount = '';
		
		$longAccount = self::clearIban($ibanAccount);

		$longAccount = self::rearrangeIban($longAccount);
		                        
		$longAccount =	substr($longAccount,2,strlen($longAccount) -2) . substr($longAccount,0, 2) ;
		
     
     	return (self::calculateRemainder($longAccount) == 1);
	}
	
	
	/**
	* checks for invalid countryCode in format or existence
	*/
	private function invalidCountryCode ($countryCode) {

		if (!preg_match('/^[A-Z]{2}$/i', $countryCode)) {
			return true;
		}

		// Maybe it could be faster a regex like DE|EN|IT|.. ?
		if (!in_array($countryCode,self::$COUNTRIES)) {
			return true;
		}
	
		return false;
	}

	/**
	* rearrangeAccount
	*/
	private function rearrangeAccount ($accountNumber,$countryCode) {
					return $accountNumber . 
								self::letterPosition(substr($countryCode,0, 1)) . 
                           self::letterPosition(substr($countryCode,1, 1)). "00";
	}

	/**
	* rearrangeIban
	*/
	private function rearrangeIban ($ibanAccount) {
					return 	substr($ibanAccount,2,strlen($ibanAccount) -2) .
		                         self::letterPosition(substr($ibanAccount,0, 1)) .
		                         	self::letterPosition(substr($ibanAccount,1, 1));
	}
	
	/**
	* workaround to perform mod operation with a big number.
	*/
	private function calculateRemainder($longNumber) {
		$division = 0;
		$remainder = 0;
		
     for ($i=0;$i

Si quieres probar esto, tendrías que escribir algo así: incluir el fichero anterior y usar directamente los métdoos estáticos de generar y validar. Hay un par de cuentas de ejemplo. Generar tiene dos parámetros opcionales. Uno booleano para decirle si queremos sacar la cuenta con el prefijo IBAN (false por defecto), y otro para decirle si queremos que saque el IBAN con separaciones (true por defecto).

<?php

include_once 'Iban.php';

//$example='2103 0166 32 1234567890';
//$expected_iban = 'ES5021030166321234567890';

$example='2100 0813 61 0123456789';
$expected_iban = 'ES79 2100 0813 6101 2345 6789';
 
echo Iban::generate($example,'ES') . ' == ';
echo $expected_iban;

if (Iban::validate('ES5021030166321234567890')) {
	echo 'valid IBAN';
	} else {
	echo 'invalid IBAN';
}

Habrás notado que el php no lo cierro con ?> . Eso es porque voy de superdelisto y de extrakwel. Pero en el fondo esto no ha sido más que un post con una rueda reinventada. Hay formas mucho más abreviadas de hacer esto.

]]> Los organismos internaciones se han vuelto a poner de acuerdo para poner unificar los números de cuenta y gracias a ello todos los programadores y DBAs del mundo ya estamos enfrascados en la tarea de adaptar programas, validaciones, campos de las BBDD y un largo etcétera.

En cada país el código de cuenta corriente puede variar y a través del IBAN se intenta unificar la forma de esa cuenta de tal forma que sea validable. Este artículo de la wikipedia lo explica bastante bien, incluyendo los pasos tanto para generar un IBAN a partir de una CC como para validarlo

Hay una pequeña pega, la validación exige una operación mod sobre un número tan grande que es probable que muchos lenguajes no puedan llevarla a cabo. En la red existen ya muchas soluciones, esta es una. Ojo, aparte de que este ejemplo solo se ha probado con cuentas en el formato de 20 dígitos esto no ha sido más que una diversión. Tienes implementaciones mejores como php-iban

NOTA:Para evitar problemas con el copy paste o posibles fallos con algún caracter, puedes descargarte esto del repositorio de git

<?php
/**
* Iban
* Simple utility class to generate and validate IBAN account numbers
* Based on http://www.lawebdelprogramador.com/foros/Visual_Basic/1409866-Calculo_IBAN.html
* @author Pello Xabier Altadill Izura
* @version    $Id:$
* @link       http://www.pello.info
* @since      Available since 2014-01-17
* @greetz	Iban (Zabalza)
*  ... and you too
*/

class Iban {
   
   private static $LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	private static $COUNTRIES = array("DE","EN","IT","NO","FR","PL","RO","SR","BG","SL","NL","RU","HU","LT","TR","CA","SV","ZH","EL","ES","SQ","PT","CS","FI","SK","DA","HR","LV","ET","JA","KA","MN");

   
   /**
   * Given a 20 digit account number, 
   * generates and returns IBAN account
   * needs refactoring
   */
	public static function generate ($accountNumber, $countryCode, $ibanPrefix=false,$spaces=true) {
		
		$longAccount = "";
		$remainder = 0;
		$prefix = ($ibanPrefix)?'IBAN':'';

		// Remove space chars, if any
		$accountNumber = self::clear($accountNumber);

		if (self::invalidCountryCode($countryCode)) {
			return 'Invalid country code: ' . $countryCode;
		}		
		
		if (self::invalidAccountNumber($accountNumber)) {
			return 'Invalid account Number: ' . $accountNumber;
		}
		

		$longAccount =  self::rearrangeAccount($accountNumber,$countryCode);

		$remainder = self::calculateRemainder($longAccount);

		if ($spaces) {
	   	return self::addSpaces($prefix . $countryCode . sprintf('%02d',(98-$remainder)) . $accountNumber);
	   } else {
	   	return $prefix . $countryCode . sprintf('%02d',(98-$remainder)) . $accountNumber;
	   }
	}
	
	/**
	* validates an IBAN account
	*
	*/
	public static function validate ($ibanAccount) {
		$longAccount = '';
		
		$longAccount = self::clearIban($ibanAccount);

		$longAccount = self::rearrangeIban($longAccount);
		                        
		$longAccount =	substr($longAccount,2,strlen($longAccount) -2) . substr($longAccount,0, 2) ;
		
     
     	return (self::calculateRemainder($longAccount) == 1);
	}
	
	
	/**
	* checks for invalid countryCode in format or existence
	*/
	private function invalidCountryCode ($countryCode) {

		if (!preg_match('/^[A-Z]{2}$/i', $countryCode)) {
			return true;
		}

		// Maybe it could be faster a regex like DE|EN|IT|.. ?
		if (!in_array($countryCode,self::$COUNTRIES)) {
			return true;
		}
	
		return false;
	}

	/**
	* rearrangeAccount
	*/
	private function rearrangeAccount ($accountNumber,$countryCode) {
					return $accountNumber . 
								self::letterPosition(substr($countryCode,0, 1)) . 
                           self::letterPosition(substr($countryCode,1, 1)). "00";
	}

	/**
	* rearrangeIban
	*/
	private function rearrangeIban ($ibanAccount) {
					return 	substr($ibanAccount,2,strlen($ibanAccount) -2) .
		                         self::letterPosition(substr($ibanAccount,0, 1)) .
		                         	self::letterPosition(substr($ibanAccount,1, 1));
	}
	
	/**
	* workaround to perform mod operation with a big number.
	*/
	private function calculateRemainder($longNumber) {
		$division = 0;
		$remainder = 0;
		
     for ($i=0;$i

Si quieres probar esto, tendrías que escribir algo así: incluir el fichero anterior y usar directamente los métdoos estáticos de generar y validar. Hay un par de cuentas de ejemplo. Generar tiene dos parámetros opcionales. Uno booleano para decirle si queremos sacar la cuenta con el prefijo IBAN (false por defecto), y otro para decirle si queremos que saque el IBAN con separaciones (true por defecto).

<?php

include_once 'Iban.php';

//$example='2103 0166 32 1234567890';
//$expected_iban = 'ES5021030166321234567890';

$example='2100 0813 61 0123456789';
$expected_iban = 'ES79 2100 0813 6101 2345 6789';
 
echo Iban::generate($example,'ES') . ' == ';
echo $expected_iban;

if (Iban::validate('ES5021030166321234567890')) {
	echo 'valid IBAN';
	} else {
	echo 'invalid IBAN';
}

Habrás notado que el php no lo cierro con ?> . Eso es porque voy de superdelisto y de extrakwel. Pero en el fondo esto no ha sido más que un post con una rueda reinventada. Hay formas mucho más abreviadas de hacer esto.

]]> http://www.pello.info/index.php/blog/calcular-el-iban-con-php MessageQueue con Spring http://www.pello.info/index.php/blog/messagequeue-con-spring http://www.pello.info/index.php/blog/messagequeue-con-spring 2014-01-06 00:08:52 pelloxabier http://www.pello.info/index.php/blog/messagequeue-con-spring

Hace unos meses salió aquí un ejemplo de ActiveMQ sin Spring ni nada, aunque lo relevante era mostrar la configuración y uso del servidor de mensajes. Vamos ahora a hacer exactamente lo mismo pero utilizando Spring. Cosa que tenía pendiente desde entonces.

Al igual que sucedía con JDBC, Spring trae unas plantillas para que nos podamos ahorrar toooodo ese código boilerplate tedioso, repetitivo que se precisa simplemente para hacer una operación sencilla. En este caso se trata de JmsTemplate.

Al contrario que otros ejemplos, aquí conviene empezar viendo el fichero xml con la definición de beans, en los que veremos cómo se declaran una serie de instancias precisas para interactuar con ActiveMQ.

El fichero de beans de Spring

Hay dos maneras de referise a la cola, puede ser de forma genérica como se ve en este ejemplo o haciendo uso de los prefijos de ActiveMQ (se ven comentados)






	







	








 

	

 
   
  
  
  
  	
  	
	
  
  
  
  
	
	
	
  
  

El emisor

Es un Thread que aleatoriamente manda una instancia de la clase Order, que no es más que un POJO que representa un pedido. Tanto en el emisor como en el receptor se aprecia que el código para interactuar con la cola de mensajes se reduce mucho.

package info.pello.spring.messagequeue;

import java.util.Random;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;


/**
 * Sends messages to apache MQ
 * @author Pello Altadill
 * @greetz to people I met in Andersen
 */
public class MessageSender extends Thread {

	private Random random;
	private JmsTemplate jmsTemplate;
	private String queueName;
	
	/**
	 * default constructor
	 */
	public MessageSender (String name) {
		super(name);
		random = new Random();
	}
	
	/**
	 * main thread loop
	 */
	public void run () {
		String [] products = {"BigMac","Chips","Coke"};
		Order order = null;
		int counter = 0;
		
		while (true) {
			try {
				sleep(random.nextInt(5));
				counter++;
				order = new Order(products[random.nextInt(3)], random.nextInt(5));
				System.out.println("["+counter+"] Sending order: " + order.toString());
				sendMessage(order);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	}

	/**
	 * sends message to queue
	 * http://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch23s03.html
	 * @param order
	 */
	private void sendMessage(final Order order) {

		jmsTemplate.send(queueName,
			new MessageCreator() {
				public Message createMessage(Session session) throws JMSException {
					return session.createObjectMessage(order);
				}
			}
		);

		
	}

	/**
	 * @return the jmsTemplate
	 */
	public JmsTemplate getJmsTemplate() {
		return jmsTemplate;
	}

	/**
	 * @param jmsTemplate the jmsTemplate to set
	 */
	public void setJmsTemplate(JmsTemplate jmsTemplate) {
		this.jmsTemplate = jmsTemplate;
	}

	/**
	 * @return the queueName
	 */
	public String getQueueName() {
		return queueName;
	}

	/**
	 * @param queueName the queueName to set
	 */
	public void setQueueName(String queueName) {
		this.queueName = queueName;
	}
}
El receptor

Otro thread que va leyendo de la cola los pedidos.

package info.pello.spring.messagequeue;

import java.util.Random;

import javax.jms.JMSException;
import javax.jms.ObjectMessage;


import org.springframework.jms.core.JmsTemplate;


/**
 * Receives messages to apache MQ
 * @author Pello Altadill
 * @greetz to people I met in Andersen
 */
public class MessageReceiver extends Thread {
	
	private Random random;
	private String queueName;
	private JmsTemplate jmsTemplate;
	
	/**
	 * default constructor
	 */
	public MessageReceiver (String name) {
		super(name);
		random = new Random();
	}
	
	/**
	 * main thread loop
	 */
	public void run () {
		Order order = null;
		int counter = 0;
		
		while (true) {
			try {
				sleep(random.nextInt(5));
				order = receiveMessage();
				
				if (null != order) {
					counter++;
					System.out.println("["+counter+"] Order rcv: " + order.toString());
				} else {
					System.out.println("Order is null ");					
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	}

	/**
	 * reads message from queue
	 * @return Order
	 */
	private Order receiveMessage() {
		try {
			ObjectMessage receivedMessage = (ObjectMessage) jmsTemplate.receive(queueName);
			Order order = (Order) receivedMessage.getObject();
			
			return order;
			} catch (JMSException jmsException) {
				System.err.println("Error reading msg: " + jmsException.getMessage());
			}
		
		return null;
		
	}


	/**
	 * @return the jmsTemplate
	 */
	public JmsTemplate getJmsTemplate() {
		return jmsTemplate;
	}

	/**
	 * @param jmsTemplate the jmsTemplate to set
	 */
	public void setJmsTemplate(JmsTemplate jmsTemplate) {
		this.jmsTemplate = jmsTemplate;
	}

	/**
	 * @return the queueName
	 */
	public String getQueueName() {
		return queueName;
	}

	/**
	 * @param queueName the queueName to set
	 */
	public void setQueueName(String queueName) {
		this.queueName = queueName;
	}
}
La clase principal

Esta clase simplemente inicia el emisor y receptor.

package info.pello.spring.messagequeue;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * Main program, starting point of our project
 * @author Pello Altadill
 * @greetz for those who keep on working even on xmas
 */
public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ApplicationContext context = new ClassPathXmlApplicationContext("messagequeue.xml");
		 
		MessageSender messageSender = (MessageSender) context.getBean("messageSender");
		MessageReceiver messageReceiver = (MessageReceiver) context.getBean("messageReceiver");

		messageSender.start();
		messageReceiver.start();
		
	}

}

Esto genera una serie de logs bastante verbosos, pero se va viendo como se pasan mensajes a través de activeMQ. Por cierto, en el servidor no hace falta hacer nada, más que ponerlo en marcha.

]]>

Hace unos meses salió aquí un ejemplo de ActiveMQ sin Spring ni nada, aunque lo relevante era mostrar la configuración y uso del servidor de mensajes. Vamos ahora a hacer exactamente lo mismo pero utilizando Spring. Cosa que tenía pendiente desde entonces.

Al igual que sucedía con JDBC, Spring trae unas plantillas para que nos podamos ahorrar toooodo ese código boilerplate tedioso, repetitivo que se precisa simplemente para hacer una operación sencilla. En este caso se trata de JmsTemplate.

Al contrario que otros ejemplos, aquí conviene empezar viendo el fichero xml con la definición de beans, en los que veremos cómo se declaran una serie de instancias precisas para interactuar con ActiveMQ.

El fichero de beans de Spring

Hay dos maneras de referise a la cola, puede ser de forma genérica como se ve en este ejemplo o haciendo uso de los prefijos de ActiveMQ (se ven comentados)






	







	








 

	

 
   
  
  
  
  	
  	
	
  
  
  
  
	
	
	
  
  

El emisor

Es un Thread que aleatoriamente manda una instancia de la clase Order, que no es más que un POJO que representa un pedido. Tanto en el emisor como en el receptor se aprecia que el código para interactuar con la cola de mensajes se reduce mucho.

package info.pello.spring.messagequeue;

import java.util.Random;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;


/**
 * Sends messages to apache MQ
 * @author Pello Altadill
 * @greetz to people I met in Andersen
 */
public class MessageSender extends Thread {

	private Random random;
	private JmsTemplate jmsTemplate;
	private String queueName;
	
	/**
	 * default constructor
	 */
	public MessageSender (String name) {
		super(name);
		random = new Random();
	}
	
	/**
	 * main thread loop
	 */
	public void run () {
		String [] products = {"BigMac","Chips","Coke"};
		Order order = null;
		int counter = 0;
		
		while (true) {
			try {
				sleep(random.nextInt(5));
				counter++;
				order = new Order(products[random.nextInt(3)], random.nextInt(5));
				System.out.println("["+counter+"] Sending order: " + order.toString());
				sendMessage(order);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	}

	/**
	 * sends message to queue
	 * http://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch23s03.html
	 * @param order
	 */
	private void sendMessage(final Order order) {

		jmsTemplate.send(queueName,
			new MessageCreator() {
				public Message createMessage(Session session) throws JMSException {
					return session.createObjectMessage(order);
				}
			}
		);

		
	}

	/**
	 * @return the jmsTemplate
	 */
	public JmsTemplate getJmsTemplate() {
		return jmsTemplate;
	}

	/**
	 * @param jmsTemplate the jmsTemplate to set
	 */
	public void setJmsTemplate(JmsTemplate jmsTemplate) {
		this.jmsTemplate = jmsTemplate;
	}

	/**
	 * @return the queueName
	 */
	public String getQueueName() {
		return queueName;
	}

	/**
	 * @param queueName the queueName to set
	 */
	public void setQueueName(String queueName) {
		this.queueName = queueName;
	}
}
El receptor

Otro thread que va leyendo de la cola los pedidos.

package info.pello.spring.messagequeue;

import java.util.Random;

import javax.jms.JMSException;
import javax.jms.ObjectMessage;


import org.springframework.jms.core.JmsTemplate;


/**
 * Receives messages to apache MQ
 * @author Pello Altadill
 * @greetz to people I met in Andersen
 */
public class MessageReceiver extends Thread {
	
	private Random random;
	private String queueName;
	private JmsTemplate jmsTemplate;
	
	/**
	 * default constructor
	 */
	public MessageReceiver (String name) {
		super(name);
		random = new Random();
	}
	
	/**
	 * main thread loop
	 */
	public void run () {
		Order order = null;
		int counter = 0;
		
		while (true) {
			try {
				sleep(random.nextInt(5));
				order = receiveMessage();
				
				if (null != order) {
					counter++;
					System.out.println("["+counter+"] Order rcv: " + order.toString());
				} else {
					System.out.println("Order is null ");					
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	}

	/**
	 * reads message from queue
	 * @return Order
	 */
	private Order receiveMessage() {
		try {
			ObjectMessage receivedMessage = (ObjectMessage) jmsTemplate.receive(queueName);
			Order order = (Order) receivedMessage.getObject();
			
			return order;
			} catch (JMSException jmsException) {
				System.err.println("Error reading msg: " + jmsException.getMessage());
			}
		
		return null;
		
	}


	/**
	 * @return the jmsTemplate
	 */
	public JmsTemplate getJmsTemplate() {
		return jmsTemplate;
	}

	/**
	 * @param jmsTemplate the jmsTemplate to set
	 */
	public void setJmsTemplate(JmsTemplate jmsTemplate) {
		this.jmsTemplate = jmsTemplate;
	}

	/**
	 * @return the queueName
	 */
	public String getQueueName() {
		return queueName;
	}

	/**
	 * @param queueName the queueName to set
	 */
	public void setQueueName(String queueName) {
		this.queueName = queueName;
	}
}
La clase principal

Esta clase simplemente inicia el emisor y receptor.

package info.pello.spring.messagequeue;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * Main program, starting point of our project
 * @author Pello Altadill
 * @greetz for those who keep on working even on xmas
 */
public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ApplicationContext context = new ClassPathXmlApplicationContext("messagequeue.xml");
		 
		MessageSender messageSender = (MessageSender) context.getBean("messageSender");
		MessageReceiver messageReceiver = (MessageReceiver) context.getBean("messageReceiver");

		messageSender.start();
		messageReceiver.start();
		
	}

}

Esto genera una serie de logs bastante verbosos, pero se va viendo como se pasan mensajes a través de activeMQ. Por cierto, en el servidor no hace falta hacer nada, más que ponerlo en marcha.

]]>
http://www.pello.info/index.php/blog/messagequeue-con-spring
Acceder a web desde Android con java.net http://www.pello.info/index.php/blog/acceder-a-web-desde-android-con-java-net http://www.pello.info/index.php/blog/acceder-a-web-desde-android-con-java-net 2013-11-23 10:36:35 pelloxabier http://www.pello.info/index.php/blog/acceder-a-web-desde-android-con-java-net Accceso a Web desde Android

Las aplicaciones para móviles se podrían dividir en tres grandes grupos: las que se ejecutan totalmente de forma local, las que tienen toda la información en la web y las que combinan las dos cosas. Si tenemos que acceder a la web desde Android y teniendo en cuenta que lo hacemos con java tenemos dos opciones por defecto:

  1. Usar las librerías básicas de java.net
  2. Usar HttpClient

HttpClient la librería de Apache
Logo pre-web ochentero

En este artículo ya mostraba un ejemplo de uso de HttpClient con Android. HttpClient es una librería que forma parte del proyecto Apache, ya va por la versión 4.3 y que aparte de tener cierto recorrido pues qué vamos a decir, tiene detrás a Apache y ya se sabe, esta gente puede decir aquella frase de los jubilados de vaya semanita: "yo traje la web a Internet chaval".

...
    /*
     * consultar
     * Hace una petición a la web
     * Todo a mano con httpclient
     * @param View v
     */
    public void consultar (View v) {
    	String url = etUrl.getText().toString();
    	HttpGet peticion = new HttpGet(url);
		HttpClient cliente = new DefaultHttpClient();
		
    	try {
			ResponseHandler respuesta = new BasicResponseHandler();
			String cuerpoRespuesta = cliente.execute(peticion,respuesta);

			if (cuerpoRespuesta != null && cuerpoRespuesta.length() > 0) {
				tvResultado.setText("OK\n: " + cuerpoRespuesta);
			} else {
				tvResultado.setText("Error\n"+cuerpoRespuesta);
			}

		} catch (ClientProtocolException e) {
			tvResultado.setText("Unexpected ClientProtocolException" + e);
		} catch (IOException e) {
			tvResultado.setText("Unexpected IOException" + e);
		}

    }
    
    /*
     * postear
     * Enví­a una petición a la web.. con POST pasando parámetros
     * @param View v
     */
    public void postear (View v) {
    	String url = etUrl.getText().toString();
    	String login = etLogin.getText().toString();
    	String password = etPassword.getText().toString();
    	
    	HttpPost peticion = null;
		HttpClient cliente = null;
		
		Vector parametros = new Vector();
		ResponseHandler respuesta = new BasicResponseHandler();
		
    	try {
    		parametros.add(new BasicNameValuePair("login", login));
    		parametros.add(new BasicNameValuePair("password", password));
    		
    		url +=  "?" + URLEncodedUtils.format(parametros, null);

    		peticion = new HttpPost(url);
			cliente = new DefaultHttpClient();
    		
			String cuerpoRespuesta = cliente.execute(peticion,respuesta);
	    	

			
			if (cuerpoRespuesta != null && cuerpoRespuesta.length() > 0) {
				tvResultado.setText("OK\n: " + cuerpoRespuesta);
			} else {
				tvResultado.setText("Inesperado: \n"+cuerpoRespuesta);
			}

		} catch (ClientProtocolException e) {
			tvResultado.setText("Unexpected ClientProtocolException" + e);
		} catch (IOException e) {
			tvResultado.setText("Unexpected IOException" + e);
		}  	
    }
...

Android trae la librería HttpClient por defecto, lo cual está muy bien, pero hay un pequeño problema. Parece ser que la versión de HttpClient que Android introduce por defecto siempre es una 4.0beta, y lo que es peor, no la cambian. Y es probable que por la web te encuentres muchos ejemplos de HttpClient y al trasladarlos a una aplicación Android haya muchas clases cruciales que no se reconocen. Así que en este post, para ejemplos simples lo que propongo es:

java.net: back to basics

A ver, si meter soporte para otras versiones de HttpClient puede ser tan simple como introducir ese jar en la App, o sencillamente buscar otras librerías que seguramente lo hacen muy bien. Esto no es más que una clase muy muy simple que tira de java.net para hacer dos cosas muy simples: GET y POST, con soporte para cookies, y sin necesidad de añadir librerías extras.



import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Hashtable;


/**
 * Simple class to make HTTP requests using standar java.net package
 * @author Pello Xabier Altadill Izura
 * @greetz 4 u
 */
public class WebRequest {
	private String userAgent;
	private String responseString;
	private int responseCode;
	private String exceptionMessage;
	private Hashtable cookies;
	
	/**
	 * default constructor
	 */
	public WebRequest () {
		this.userAgent = "EvilBlackDeathOfDoom browser v1.0";
		cookies = new Hashtable();
	}

	/**
	 * makes GET request to URL
	 * @param urlString to request
	 * @return true if everything went fine, false otherwise
	 */
	public boolean get (String urlString) {
		boolean result = false;
		responseString = "";
		exceptionMessage = "";
		String line = "";
		
		
		try {
				// Create an URL instance
			   URL url = new URL(urlString);
			   
		       // Create the HttpConnection
			   HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		       connection.setRequestProperty("User-Agent", userAgent); 
		       connection.setRequestMethod("GET");
		       setCookies(connection);

		        // Get input stream from server
		        BufferedReader in = new BufferedReader(new InputStreamReader(
		                                    connection.getInputStream()));
		    // Read response from server
		    while ((line = in.readLine()) != null) {
		    	responseString += line;
		    }
		    
		    in.close();
		return true;
		
	    } catch (IOException e) {
		  exceptionMessage = e.getMessage();
		  e.printStackTrace();
		} catch (Exception e) {
		  exceptionMessage = e.getMessage();	    	
		}
		
		return false;
		
	}
	
	/**
	 * makes POST request to URL
	 * @param url to request
	 * @param parameters for POST
	 * @return true if everything went fine, false otherwise
	 */
	public boolean post (String urlString, Hashtable parameters) {
		boolean result = false;
	    String line = "";
	    String postString = "";
	    String parameterValue = "";
		responseString = "";
		exceptionMessage = "";

			try {

		        URL url = new URL(urlString);
		        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		        connection.setRequestMethod("POST");
		        connection.setRequestProperty("User-Agent", userAgent); 
		        connection.setDoOutput(true);
		        setCookies(connection);

		        OutputStreamWriter output = new OutputStreamWriter(
		                                         connection.getOutputStream());
		        
		        
		        // We set parameters one by one
			    for (String parameterName : parameters.keySet()) {
			    	parameterValue = URLEncoder.encode(parameters.get(parameterName),"UTF-8");
			    	postString += parameterName + "=" +parameterValue +"&";
			     }
			    
			    output.write(postString);
		        output.close();

		        // Now we get the response
		        BufferedReader in = new BufferedReader(
		                                    new InputStreamReader(
		                                    connection.getInputStream()));
		        
		      getCookies(connection);
		      responseCode = connection.getResponseCode();
		      
		      while ((line = in.readLine()) != null) {
		        responseString += line;
		      }
		      in.close();
		     return true;
		     
		    } catch (IOException e) {
		      exceptionMessage = e.getMessage();
		      e.printStackTrace();
		    } catch (Exception e) {
			  exceptionMessage = e.getMessage();	    	
		      e.printStackTrace();
		    }
			return false;
	}
	
	/**
	 * sends previously saved cookies to server.
	 * This method restores cookie name=value pairs from cookies hashtable
	 * and puts them in request header:
	 *  cookiename1=value1; cookiename2=value2;..
	 * @param connection
	 */
	private void setCookies(HttpURLConnection connection) {
		String cookieString = "";

		// Get cookies name=value pair from hashtable
		for (String cookieName : cookies.keySet()) {
			cookieString += cookieName + "=" + cookies.get(cookieName) + ";";
		}
		
		// and put them in the request header
		System.out.println("Sending cookies to server: " + cookieString);
		connection.setRequestProperty("Cookies", cookieString);
	}

	/**
	 * retrieves Cookies sent by server
	 * Cookies come in this form:
	 *  Set-Cookie: name1=value1;
	 *  Set-Cookie: name2=value2;
	 *  ...
	 * So we have to retrieve every Set-Cookie line and parse cookie name and value
	 * This method stores cookie data in the cookies Hashtable for further use
	 * @param connection
	 */
	private void getCookies(HttpURLConnection connection) {
		String headerName=null;
		String cookieString = "";
        String cookieName = "";
        String cookieValue = "";        
        
		// We look up for Set-Cookie entries in header
		for (int i=1; (headerName = connection.getHeaderFieldKey(i))!=null; i++) {
		 	if (headerName.equals("Set-Cookie")) {                  
		 		cookieString = connection.getHeaderField(i);   
		        cookieString = cookieString.substring(0, cookieString.indexOf(";"));
		        cookieName = cookieString.substring(0, cookieString.indexOf("="));
		        cookieValue = cookieString.substring(cookieString.indexOf("=") + 1, cookieString.length());
		        cookies.put(cookieName, cookieValue);
		        System.out.println("One cookie, mmm yummy: " + cookieName + "=" + cookieValue);
		    }
		}
	}

	/**
	 * @return the userAgent
	 */
	public String getUserAgent() {
		return userAgent;
	}

	/**
	 * @param userAgent the userAgent to set
	 */
	public void setUserAgent(String userAgent) {
		this.userAgent = userAgent;
	}

	/**
	 * @return the responseString
	 */
	public String getResponseString() {
		return responseString;
	}

	/**
	 * @param responseString the responseString to set
	 */
	public void setResponseString(String responseString) {
		this.responseString = responseString;
	}

	/**
	 * @return the responseCode
	 */
	public int getResponseCode() {
		return responseCode;
	}

	/**
	 * @param responseCode the responseCode to set
	 */
	public void setResponseCode(int responseCode) {
		this.responseCode = responseCode;
	}

	/**
	 * @return the exceptionMessage
	 */
	public String getExceptionMessage() {
		return exceptionMessage;
	}

	/**
	 * @param exceptionMessage the exceptionMessage to set
	 */
	public void setExceptionMessage(String exceptionMessage) {
		this.exceptionMessage = exceptionMessage;
	}
}

Esta sería la clase principal para hacer pruebas, que en este caso se hizo con éxito contra una aplicación php que me facilitó amablemente Eugenia. Como se puede apreciar hay un ejemplo de get y otro de post, y el uso de la clase WebRequest es muy muy sencillo.

import java.util.Hashtable;



/**
*
* @author Pello Altadill
* @greetz blue mugs
*/
public class Main {
	public static void main (String args[]) {
		WebRequest webRequest = new WebRequest();
		
		if (webRequest.get("http://192.168.77.104/labs/Ejemplo1DAM/index.php")) {
			System.out.println("OK: " + webRequest.getResponseString());
		} else {
			System.out.println("Error: " + webRequest.getExceptionMessage());			
		}
		
		Hashtable parameters = new Hashtable();
		parameters.put("usuario", "falken");
		parameters.put("password", "josua");
		
		if (webRequest.post("http://192.168.77.104/labs/Ejemplo1DAM/consultarUsuario.php", parameters)) {
			System.out.println("OK login: " + webRequest.getResponseString() + "\n" + webRequest.getResponseCode());
		} else {
			System.out.println("Error: " + webRequest.getExceptionMessage() + "\n" + webRequest.getResponseCode());			
		}
		

	}
}

Puedes descargarte este ejemplo aquí. Necesita bastantes mejoras y la primera sería añadir el soporte para redirects.

]]>
Accceso a Web desde Android

Las aplicaciones para móviles se podrían dividir en tres grandes grupos: las que se ejecutan totalmente de forma local, las que tienen toda la información en la web y las que combinan las dos cosas. Si tenemos que acceder a la web desde Android y teniendo en cuenta que lo hacemos con java tenemos dos opciones por defecto:

  1. Usar las librerías básicas de java.net
  2. Usar HttpClient

HttpClient la librería de Apache
Logo pre-web ochentero

En este artículo ya mostraba un ejemplo de uso de HttpClient con Android. HttpClient es una librería que forma parte del proyecto Apache, ya va por la versión 4.3 y que aparte de tener cierto recorrido pues qué vamos a decir, tiene detrás a Apache y ya se sabe, esta gente puede decir aquella frase de los jubilados de vaya semanita: "yo traje la web a Internet chaval".

...
    /*
     * consultar
     * Hace una petición a la web
     * Todo a mano con httpclient
     * @param View v
     */
    public void consultar (View v) {
    	String url = etUrl.getText().toString();
    	HttpGet peticion = new HttpGet(url);
		HttpClient cliente = new DefaultHttpClient();
		
    	try {
			ResponseHandler respuesta = new BasicResponseHandler();
			String cuerpoRespuesta = cliente.execute(peticion,respuesta);

			if (cuerpoRespuesta != null && cuerpoRespuesta.length() > 0) {
				tvResultado.setText("OK\n: " + cuerpoRespuesta);
			} else {
				tvResultado.setText("Error\n"+cuerpoRespuesta);
			}

		} catch (ClientProtocolException e) {
			tvResultado.setText("Unexpected ClientProtocolException" + e);
		} catch (IOException e) {
			tvResultado.setText("Unexpected IOException" + e);
		}

    }
    
    /*
     * postear
     * Enví­a una petición a la web.. con POST pasando parámetros
     * @param View v
     */
    public void postear (View v) {
    	String url = etUrl.getText().toString();
    	String login = etLogin.getText().toString();
    	String password = etPassword.getText().toString();
    	
    	HttpPost peticion = null;
		HttpClient cliente = null;
		
		Vector parametros = new Vector();
		ResponseHandler respuesta = new BasicResponseHandler();
		
    	try {
    		parametros.add(new BasicNameValuePair("login", login));
    		parametros.add(new BasicNameValuePair("password", password));
    		
    		url +=  "?" + URLEncodedUtils.format(parametros, null);

    		peticion = new HttpPost(url);
			cliente = new DefaultHttpClient();
    		
			String cuerpoRespuesta = cliente.execute(peticion,respuesta);
	    	

			
			if (cuerpoRespuesta != null && cuerpoRespuesta.length() > 0) {
				tvResultado.setText("OK\n: " + cuerpoRespuesta);
			} else {
				tvResultado.setText("Inesperado: \n"+cuerpoRespuesta);
			}

		} catch (ClientProtocolException e) {
			tvResultado.setText("Unexpected ClientProtocolException" + e);
		} catch (IOException e) {
			tvResultado.setText("Unexpected IOException" + e);
		}  	
    }
...

Android trae la librería HttpClient por defecto, lo cual está muy bien, pero hay un pequeño problema. Parece ser que la versión de HttpClient que Android introduce por defecto siempre es una 4.0beta, y lo que es peor, no la cambian. Y es probable que por la web te encuentres muchos ejemplos de HttpClient y al trasladarlos a una aplicación Android haya muchas clases cruciales que no se reconocen. Así que en este post, para ejemplos simples lo que propongo es:

java.net: back to basics

A ver, si meter soporte para otras versiones de HttpClient puede ser tan simple como introducir ese jar en la App, o sencillamente buscar otras librerías que seguramente lo hacen muy bien. Esto no es más que una clase muy muy simple que tira de java.net para hacer dos cosas muy simples: GET y POST, con soporte para cookies, y sin necesidad de añadir librerías extras.



import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Hashtable;


/**
 * Simple class to make HTTP requests using standar java.net package
 * @author Pello Xabier Altadill Izura
 * @greetz 4 u
 */
public class WebRequest {
	private String userAgent;
	private String responseString;
	private int responseCode;
	private String exceptionMessage;
	private Hashtable cookies;
	
	/**
	 * default constructor
	 */
	public WebRequest () {
		this.userAgent = "EvilBlackDeathOfDoom browser v1.0";
		cookies = new Hashtable();
	}

	/**
	 * makes GET request to URL
	 * @param urlString to request
	 * @return true if everything went fine, false otherwise
	 */
	public boolean get (String urlString) {
		boolean result = false;
		responseString = "";
		exceptionMessage = "";
		String line = "";
		
		
		try {
				// Create an URL instance
			   URL url = new URL(urlString);
			   
		       // Create the HttpConnection
			   HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		       connection.setRequestProperty("User-Agent", userAgent); 
		       connection.setRequestMethod("GET");
		       setCookies(connection);

		        // Get input stream from server
		        BufferedReader in = new BufferedReader(new InputStreamReader(
		                                    connection.getInputStream()));
		    // Read response from server
		    while ((line = in.readLine()) != null) {
		    	responseString += line;
		    }
		    
		    in.close();
		return true;
		
	    } catch (IOException e) {
		  exceptionMessage = e.getMessage();
		  e.printStackTrace();
		} catch (Exception e) {
		  exceptionMessage = e.getMessage();	    	
		}
		
		return false;
		
	}
	
	/**
	 * makes POST request to URL
	 * @param url to request
	 * @param parameters for POST
	 * @return true if everything went fine, false otherwise
	 */
	public boolean post (String urlString, Hashtable parameters) {
		boolean result = false;
	    String line = "";
	    String postString = "";
	    String parameterValue = "";
		responseString = "";
		exceptionMessage = "";

			try {

		        URL url = new URL(urlString);
		        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		        connection.setRequestMethod("POST");
		        connection.setRequestProperty("User-Agent", userAgent); 
		        connection.setDoOutput(true);
		        setCookies(connection);

		        OutputStreamWriter output = new OutputStreamWriter(
		                                         connection.getOutputStream());
		        
		        
		        // We set parameters one by one
			    for (String parameterName : parameters.keySet()) {
			    	parameterValue = URLEncoder.encode(parameters.get(parameterName),"UTF-8");
			    	postString += parameterName + "=" +parameterValue +"&";
			     }
			    
			    output.write(postString);
		        output.close();

		        // Now we get the response
		        BufferedReader in = new BufferedReader(
		                                    new InputStreamReader(
		                                    connection.getInputStream()));
		        
		      getCookies(connection);
		      responseCode = connection.getResponseCode();
		      
		      while ((line = in.readLine()) != null) {
		        responseString += line;
		      }
		      in.close();
		     return true;
		     
		    } catch (IOException e) {
		      exceptionMessage = e.getMessage();
		      e.printStackTrace();
		    } catch (Exception e) {
			  exceptionMessage = e.getMessage();	    	
		      e.printStackTrace();
		    }
			return false;
	}
	
	/**
	 * sends previously saved cookies to server.
	 * This method restores cookie name=value pairs from cookies hashtable
	 * and puts them in request header:
	 *  cookiename1=value1; cookiename2=value2;..
	 * @param connection
	 */
	private void setCookies(HttpURLConnection connection) {
		String cookieString = "";

		// Get cookies name=value pair from hashtable
		for (String cookieName : cookies.keySet()) {
			cookieString += cookieName + "=" + cookies.get(cookieName) + ";";
		}
		
		// and put them in the request header
		System.out.println("Sending cookies to server: " + cookieString);
		connection.setRequestProperty("Cookies", cookieString);
	}

	/**
	 * retrieves Cookies sent by server
	 * Cookies come in this form:
	 *  Set-Cookie: name1=value1;
	 *  Set-Cookie: name2=value2;
	 *  ...
	 * So we have to retrieve every Set-Cookie line and parse cookie name and value
	 * This method stores cookie data in the cookies Hashtable for further use
	 * @param connection
	 */
	private void getCookies(HttpURLConnection connection) {
		String headerName=null;
		String cookieString = "";
        String cookieName = "";
        String cookieValue = "";        
        
		// We look up for Set-Cookie entries in header
		for (int i=1; (headerName = connection.getHeaderFieldKey(i))!=null; i++) {
		 	if (headerName.equals("Set-Cookie")) {                  
		 		cookieString = connection.getHeaderField(i);   
		        cookieString = cookieString.substring(0, cookieString.indexOf(";"));
		        cookieName = cookieString.substring(0, cookieString.indexOf("="));
		        cookieValue = cookieString.substring(cookieString.indexOf("=") + 1, cookieString.length());
		        cookies.put(cookieName, cookieValue);
		        System.out.println("One cookie, mmm yummy: " + cookieName + "=" + cookieValue);
		    }
		}
	}

	/**
	 * @return the userAgent
	 */
	public String getUserAgent() {
		return userAgent;
	}

	/**
	 * @param userAgent the userAgent to set
	 */
	public void setUserAgent(String userAgent) {
		this.userAgent = userAgent;
	}

	/**
	 * @return the responseString
	 */
	public String getResponseString() {
		return responseString;
	}

	/**
	 * @param responseString the responseString to set
	 */
	public void setResponseString(String responseString) {
		this.responseString = responseString;
	}

	/**
	 * @return the responseCode
	 */
	public int getResponseCode() {
		return responseCode;
	}

	/**
	 * @param responseCode the responseCode to set
	 */
	public void setResponseCode(int responseCode) {
		this.responseCode = responseCode;
	}

	/**
	 * @return the exceptionMessage
	 */
	public String getExceptionMessage() {
		return exceptionMessage;
	}

	/**
	 * @param exceptionMessage the exceptionMessage to set
	 */
	public void setExceptionMessage(String exceptionMessage) {
		this.exceptionMessage = exceptionMessage;
	}
}

Esta sería la clase principal para hacer pruebas, que en este caso se hizo con éxito contra una aplicación php que me facilitó amablemente Eugenia. Como se puede apreciar hay un ejemplo de get y otro de post, y el uso de la clase WebRequest es muy muy sencillo.

import java.util.Hashtable;



/**
*
* @author Pello Altadill
* @greetz blue mugs
*/
public class Main {
	public static void main (String args[]) {
		WebRequest webRequest = new WebRequest();
		
		if (webRequest.get("http://192.168.77.104/labs/Ejemplo1DAM/index.php")) {
			System.out.println("OK: " + webRequest.getResponseString());
		} else {
			System.out.println("Error: " + webRequest.getExceptionMessage());			
		}
		
		Hashtable parameters = new Hashtable();
		parameters.put("usuario", "falken");
		parameters.put("password", "josua");
		
		if (webRequest.post("http://192.168.77.104/labs/Ejemplo1DAM/consultarUsuario.php", parameters)) {
			System.out.println("OK login: " + webRequest.getResponseString() + "\n" + webRequest.getResponseCode());
		} else {
			System.out.println("Error: " + webRequest.getExceptionMessage() + "\n" + webRequest.getResponseCode());			
		}
		

	}
}

Puedes descargarte este ejemplo aquí. Necesita bastantes mejoras y la primera sería añadir el soporte para redirects.

]]>
http://www.pello.info/index.php/blog/acceder-a-web-desde-android-con-java-net
Maneras de integrar Struts2 con Hibernate http://www.pello.info/index.php/blog/maneras-de-integrar-struts2-con-hibernate http://www.pello.info/index.php/blog/maneras-de-integrar-struts2-con-hibernate 2013-11-17 15:26:23 pelloxabier http://www.pello.info/index.php/blog/maneras-de-integrar-struts2-con-hibernate Struts2 sigue siendo uno de los frameworks web para java más populares. Lo del número 2 no está de más ya que ciertamente Struts2 y Struts a secas no tienen mucho que ver en cuanto a código. Aunque sí, formalmente los dos son frameworks MVC. Pero con Struts2 no es suficiente, ¿qué pasa con el acceso a los datos? Para facilitar la gestión de datos y ante todo poder centrarnos en el negocio y no andar por ejemplo cargando listas de objetos a mano de un resultset de jdbc disponemos de Hibernate, una pareja de baile ideal para Struts.

Hibernate logo
La sesión de Hibernate

Hibernate permite a nuestra aplicación abstraerse de la base de datos, hasta el punto siempre deseable en el que podemos cambiar la Base de datos tocando un fichero de configuración ajeno al código. Para que nuestra aplicación pueda acceder a los datos lo debe hacer a través de Hibernate y TODOS los accesos de Hibernate deben hacerse a través de una instancia de la clase Session. En una aplicación de consola por ejemplo, la clase java que pretenda acceder a los datos primero deberá conseguir una instancia de Session. Eso se suele hacer a través de una clase como esta

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
  
/**
 * provide Hibernate Session factory
 * @author Pello Xabier Altadill Izura
 * @greetz blue mug
 */
public class HibernateSession {
  
    private static final SessionFactory sessionFactory = buildSessionFactory();
    private static Session session;
  
    /**
     * Based on hibernate.cfg.xml configuration creates
     * a SessionFactory
     * @return the session factory
     */
    private static SessionFactory buildSessionFactory() {
            Configuration configuration = new Configuration();
            configuration.configure();
            ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();        
            SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
            return sessionFactory;
    }
  
    /**
     * this gives the desired session factory
     * @return hibernate Session Factory instance
     */
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
    
    /**
     * gives the current Session
     * @return Hibernate Session
     */
    public static Session getSession () {
        if (null == session) {
                session = sessionFactory.openSession();
        }
        
        return session;
    }
}

Como se puede ver, lo que hace esta clase básicamente es cargar la configuración de Hibernate que se mete en el fichero hibernate.cfg.xml, y simplemente devuelve una instancia de Session. En la clase java que utilizar Hibernate accedemos y usamos la sesión de esta manera:

        /*
         * inserts a new seller in database
         * retrieves generated id and sets to seller instance
         * @param new seller
         */
        public void insert(Seller seller) {
            SessionFactory sessionFactory = HibernateSession.getSessionFactory();
            Session session = sessionFactory.openSession();
            session.beginTransaction();
         
            Integer id = (Integer) session.save(seller);
            seller.setId(id);
                 
            session.getTransaction().commit();
                 
            session.close();

        }

Hasta aquí todo ok, y en una aplicación de consola no hay problemas. Pero... ¿Cómo nos lo montamos en Struts2 para que nuestrar clases puedan sacar una instancia de Session de Hibernate? A continuación muestro tres maneras que se mencionan con frecuencia:

1. Usando el contexto de Servlet

Mykong, un habitual de las recetas J2EE indica que ya que no existe una forma oficial de integrar los dos frameworks, se pueden utilizar el contexto. ¿cuál es el contexto en Struts2? No estamos en consola, estamos en un contexto de Servlet. Así que lo que hace es una clase que genera la Session que implementa ServletContextListener, lo cual nos va a permitir conseguir la sesión en cualquier clase dentro de la aplicación Struts2. Se puede ver este ejemplo, y en concreto el funcionamiento se ve en las clases HibernateListener.java, CustomerAction.java y el listener que se configura en web.xml.

2. Usando una librería que lo integra por anotaciones

No es oficial pero existe un proyecto alojado en googlecode con el que se hace mucho más fácil. No tenemos más que instalar un fichero jar y con un par de anotaciones ya tenemos nuestro Factory y nuestra Session inyectados de forma automática:

...
import com.googlecode.s2hibernate.struts2.plugin.annotations.SessionTarget;
import com.googlecode.s2hibernate.struts2.plugin.annotations.TransactionTarget;

/**
* Implementation of UserDAO interface
* @author Pellop Altadill
* @greetz again and again
*/
public class UserDAOImpl implements UserDAO {
	
	@SessionTarget
	Session session;
	
	@TransactionTarget
	Transaction transaction;

	/**
	 * Used to save or update a user.
	 */
	@Override
	public void saveOrUpdateUser(User user) {
		try {
			session.saveOrUpdate(user);
		} catch (Exception e) {
			transaction.rollback();
			e.printStackTrace();
		}
	}
...

El único problema de esto es que esa librería no se ha actualizado desde 2010. Por tanto pese a que es la forma más simple de todas a la larga no ofrece muchas garantías.

3. Usar Hibernate como si nada

Bueno, otra opción es hacerlo de manera normal, como si estuvieramos en una aplicación de consola. En un post de otro clásico de los blogs J2EE, Viral Patel lo hace sin ningún tipo de medida especial. Para la Session crea una clase llamada HibernateUtil que es la que provee la Session. Utilizamos la clase previa de HibernateSession y la utilizamos en las clases DAO.

Proyecto en acción

Como muestra de esta integración en esta url tienes un proyecto de Eclipse listo desarrollado en Struts2 e Hibernate. Esta hecho desde 0 mano, sin Maven ni nada ya que hay gente a mi alrededor que con su Windows8 Maven le explota en la cara.

]]>
Struts2 sigue siendo uno de los frameworks web para java más populares. Lo del número 2 no está de más ya que ciertamente Struts2 y Struts a secas no tienen mucho que ver en cuanto a código. Aunque sí, formalmente los dos son frameworks MVC. Pero con Struts2 no es suficiente, ¿qué pasa con el acceso a los datos? Para facilitar la gestión de datos y ante todo poder centrarnos en el negocio y no andar por ejemplo cargando listas de objetos a mano de un resultset de jdbc disponemos de Hibernate, una pareja de baile ideal para Struts.

Hibernate logo
La sesión de Hibernate

Hibernate permite a nuestra aplicación abstraerse de la base de datos, hasta el punto siempre deseable en el que podemos cambiar la Base de datos tocando un fichero de configuración ajeno al código. Para que nuestra aplicación pueda acceder a los datos lo debe hacer a través de Hibernate y TODOS los accesos de Hibernate deben hacerse a través de una instancia de la clase Session. En una aplicación de consola por ejemplo, la clase java que pretenda acceder a los datos primero deberá conseguir una instancia de Session. Eso se suele hacer a través de una clase como esta

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
  
/**
 * provide Hibernate Session factory
 * @author Pello Xabier Altadill Izura
 * @greetz blue mug
 */
public class HibernateSession {
  
    private static final SessionFactory sessionFactory = buildSessionFactory();
    private static Session session;
  
    /**
     * Based on hibernate.cfg.xml configuration creates
     * a SessionFactory
     * @return the session factory
     */
    private static SessionFactory buildSessionFactory() {
            Configuration configuration = new Configuration();
            configuration.configure();
            ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();        
            SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
            return sessionFactory;
    }
  
    /**
     * this gives the desired session factory
     * @return hibernate Session Factory instance
     */
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
    
    /**
     * gives the current Session
     * @return Hibernate Session
     */
    public static Session getSession () {
        if (null == session) {
                session = sessionFactory.openSession();
        }
        
        return session;
    }
}

Como se puede ver, lo que hace esta clase básicamente es cargar la configuración de Hibernate que se mete en el fichero hibernate.cfg.xml, y simplemente devuelve una instancia de Session. En la clase java que utilizar Hibernate accedemos y usamos la sesión de esta manera:

        /*
         * inserts a new seller in database
         * retrieves generated id and sets to seller instance
         * @param new seller
         */
        public void insert(Seller seller) {
            SessionFactory sessionFactory = HibernateSession.getSessionFactory();
            Session session = sessionFactory.openSession();
            session.beginTransaction();
         
            Integer id = (Integer) session.save(seller);
            seller.setId(id);
                 
            session.getTransaction().commit();
                 
            session.close();

        }

Hasta aquí todo ok, y en una aplicación de consola no hay problemas. Pero... ¿Cómo nos lo montamos en Struts2 para que nuestrar clases puedan sacar una instancia de Session de Hibernate? A continuación muestro tres maneras que se mencionan con frecuencia:

1. Usando el contexto de Servlet

Mykong, un habitual de las recetas J2EE indica que ya que no existe una forma oficial de integrar los dos frameworks, se pueden utilizar el contexto. ¿cuál es el contexto en Struts2? No estamos en consola, estamos en un contexto de Servlet. Así que lo que hace es una clase que genera la Session que implementa ServletContextListener, lo cual nos va a permitir conseguir la sesión en cualquier clase dentro de la aplicación Struts2. Se puede ver este ejemplo, y en concreto el funcionamiento se ve en las clases HibernateListener.java, CustomerAction.java y el listener que se configura en web.xml.

2. Usando una librería que lo integra por anotaciones

No es oficial pero existe un proyecto alojado en googlecode con el que se hace mucho más fácil. No tenemos más que instalar un fichero jar y con un par de anotaciones ya tenemos nuestro Factory y nuestra Session inyectados de forma automática:

...
import com.googlecode.s2hibernate.struts2.plugin.annotations.SessionTarget;
import com.googlecode.s2hibernate.struts2.plugin.annotations.TransactionTarget;

/**
* Implementation of UserDAO interface
* @author Pellop Altadill
* @greetz again and again
*/
public class UserDAOImpl implements UserDAO {
	
	@SessionTarget
	Session session;
	
	@TransactionTarget
	Transaction transaction;

	/**
	 * Used to save or update a user.
	 */
	@Override
	public void saveOrUpdateUser(User user) {
		try {
			session.saveOrUpdate(user);
		} catch (Exception e) {
			transaction.rollback();
			e.printStackTrace();
		}
	}
...

El único problema de esto es que esa librería no se ha actualizado desde 2010. Por tanto pese a que es la forma más simple de todas a la larga no ofrece muchas garantías.

3. Usar Hibernate como si nada

Bueno, otra opción es hacerlo de manera normal, como si estuvieramos en una aplicación de consola. En un post de otro clásico de los blogs J2EE, Viral Patel lo hace sin ningún tipo de medida especial. Para la Session crea una clase llamada HibernateUtil que es la que provee la Session. Utilizamos la clase previa de HibernateSession y la utilizamos en las clases DAO.

Proyecto en acción

Como muestra de esta integración en esta url tienes un proyecto de Eclipse listo desarrollado en Struts2 e Hibernate. Esta hecho desde 0 mano, sin Maven ni nada ya que hay gente a mi alrededor que con su Windows8 Maven le explota en la cara.

]]>
http://www.pello.info/index.php/blog/maneras-de-integrar-struts2-con-hibernate
Arreglar e Iniciar el Oracle Enterprise Manager http://www.pello.info/index.php/blog/arreglar-e-iniciar-el-oracle-enterprise-manager http://www.pello.info/index.php/blog/arreglar-e-iniciar-el-oracle-enterprise-manager 2013-11-10 01:01:04 pelloxabier http://www.pello.info/index.php/blog/arreglar-e-iniciar-el-oracle-enterprise-manager

Hablar de Oracle trae gratos recuerdos como la saga de IronMan y en especial la tercera entrega donde me transportaron a la nube de Oracle. El Enterprise Manager es un interfaz web con el que podemos gestionar la BD de Oracle: inicio/parada/blackout, ficheros, memoria, tareas, backups, usuarios, roles, y en definitiva todos los objetos que forman parte de los esquemas.

Pero no todo son parabienes. Tras una instalación aparentemente correcta de Oracle 11gr2 puede que el EM no arranque correctamente o de algún error. Puede ocurrir también que según el nombre de host, si por lo que sea no le gusta a Oracle no se pueda iniciar correctamente EM; por ejemplo por tener caracteres no admitidos en el nombre como _ : mi_nombre_de_host

¡Ojo! si quieres que al enterprise manager se pueda acceder desde equipos remotos tienes que meter un host reconocible desde fuera. Lo que se explica aquí es para trabajar con una instalación local.

Otra opción sería acceder a este equipo por Terminal Server y desde ahí al EM.

1. Cambia/añade nombre de host

Tenemos dos opciones, o bien cambiar el nombre de host, cosa que puede resultar peliaguda (no imposible como los antiguos SQLServer) con una instalación ya hecha, o bien darle al equipo otro nombre extra. Para eso, tanto en windows como en linux debemos cambiar el fichero hosts. Ese fichero es el primer DNS que un sistema mira para resolver nombres. No es más que un ficherillo de texto donde se introducen direcciones ip y su correspondiete nombre (o nombres) de host.

En linux se encuentra en /etc/hosts

En windows está en c:\Windows\System32\Drivers\net\hosts

Al editar ese fichero debes crear una entrada en la que indiques la dirección ip y seguidamente el nombre de host que quieras dar a tu máquina, con o sin dominio o ambos dos seguidos

192.168.1.42 orcl orcl.dominio.lan

Y por lo que más quieras. Esto es un mundo anglosajón. En algo tan crítico como un nombre de host en redes TCP/IP, que se remontan a los 70, no te empeñes en poner tildes, eñes, ni llames a tu equipo iñaki_el_pingüino_molón. Llama a tu host gandalf si quieres, renunciarás al castellano pero abrazarás un mundo con caracteres ascii de 7 bits con el que las cosas simplemente funcionan.

Asegúrate de que el cambio es correcto haciendo un ping en tu propia máquina:

ping orcl.dominio.lan

2. Modifica configuración de host Oracle

Si todo es correcto ahora debes cambiar la configuración en los listener.ora y tnsnames.ora. Básicamente ahí donde aparezca la palabra HOST indica el host que has metido.

En el listener.ora:

…
LISTENER =
 (DESCRIPTION_LIST =
   (DESCRIPTION =
     (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
     (ADDRESS = (PROTOCOL = TCP)(HOST = orcl.dominio.lan)(PORT = 1521))
   )
 )
...

En el tnsnames.ora:

…
ORCL =
 (DESCRIPTION =
   (ADDRESS = (PROTOCOL = TCP)(HOST = orcl.dominio.lan)(PORT = 1521))
   (CONNECT_DATA =
     (SERVER = DEDICATED)
     (SERVICE_NAME = orcl.dominio.lan)
   )
 )
...

NOTA: si tienes más de una BBDD basta con que cambies el host de uno de ellos, si quieres asignar más de un host crea más entradas en el

3. Tiramos el Enterprise Manager

Vamos a la consola. Previamente establecemos en la consola estas variables de entorno. No hace falta ponerlas fijas si no queremos, ahora las necesitamos para que esto arranque:

c:\DOS\> set ORACLE_SID=orcl

c:\DOS\ > set ORACLE_UNQNAME=orcl

c:\DOS\> set ORACLE_HOSTNAME=orcl.dominio.lan

Y ahora lanzamos este comando para tirar el Enterprise Manager

c:\> emca -deconfig dbcontrol db -repos drop

Esto inicia un asistente en el que indicamos SID y contraseñas y sigue para adelante.

Se supone que elimina el usuario SYSMAN. Si no fuera así, tenemos que hacerlo a mano ejecutando estas sentencias:

DROP USER sysman CASCADE;

DROP PUBLIC SYNONYM setemviewusercontext;

DROP ROLE mgmt_user;

DROP PUBLIC SYNONYM mgmt_target_blackouts;

DROP USER mgmt_view;

4. Regeneramos el Enterprise Manager

Usando la misma sesión de antes ejecutamos:

c:\DOS\> emca -config dbcontrol db -repos create

Eso inicia un asistente como el anterior. Al cabo de unos minutos, nos mostrará la URL del Enterprise Manager. Asegúrate de que tu navegador no va a un proxy o añade las excepciones necesarias si es preciso. Ya podrás entrar en tu EM.

¿No puedes entrar tampoco? ¿Te ha dado algún error? Una nota: debes ser Administrador de sistema para hacerlo. Y otra cosa importante. El comando anterior, en caso de errores genera unos logs y además te indica dónde están. Ábrelos y ahí tendrás la explicación del problema que ha encontrado.

]]>

Hablar de Oracle trae gratos recuerdos como la saga de IronMan y en especial la tercera entrega donde me transportaron a la nube de Oracle. El Enterprise Manager es un interfaz web con el que podemos gestionar la BD de Oracle: inicio/parada/blackout, ficheros, memoria, tareas, backups, usuarios, roles, y en definitiva todos los objetos que forman parte de los esquemas.

Pero no todo son parabienes. Tras una instalación aparentemente correcta de Oracle 11gr2 puede que el EM no arranque correctamente o de algún error. Puede ocurrir también que según el nombre de host, si por lo que sea no le gusta a Oracle no se pueda iniciar correctamente EM; por ejemplo por tener caracteres no admitidos en el nombre como _ : mi_nombre_de_host

¡Ojo! si quieres que al enterprise manager se pueda acceder desde equipos remotos tienes que meter un host reconocible desde fuera. Lo que se explica aquí es para trabajar con una instalación local.

Otra opción sería acceder a este equipo por Terminal Server y desde ahí al EM.

1. Cambia/añade nombre de host

Tenemos dos opciones, o bien cambiar el nombre de host, cosa que puede resultar peliaguda (no imposible como los antiguos SQLServer) con una instalación ya hecha, o bien darle al equipo otro nombre extra. Para eso, tanto en windows como en linux debemos cambiar el fichero hosts. Ese fichero es el primer DNS que un sistema mira para resolver nombres. No es más que un ficherillo de texto donde se introducen direcciones ip y su correspondiete nombre (o nombres) de host.

En linux se encuentra en /etc/hosts

En windows está en c:\Windows\System32\Drivers\net\hosts

Al editar ese fichero debes crear una entrada en la que indiques la dirección ip y seguidamente el nombre de host que quieras dar a tu máquina, con o sin dominio o ambos dos seguidos

192.168.1.42 orcl orcl.dominio.lan

Y por lo que más quieras. Esto es un mundo anglosajón. En algo tan crítico como un nombre de host en redes TCP/IP, que se remontan a los 70, no te empeñes en poner tildes, eñes, ni llames a tu equipo iñaki_el_pingüino_molón. Llama a tu host gandalf si quieres, renunciarás al castellano pero abrazarás un mundo con caracteres ascii de 7 bits con el que las cosas simplemente funcionan.

Asegúrate de que el cambio es correcto haciendo un ping en tu propia máquina:

ping orcl.dominio.lan

2. Modifica configuración de host Oracle

Si todo es correcto ahora debes cambiar la configuración en los listener.ora y tnsnames.ora. Básicamente ahí donde aparezca la palabra HOST indica el host que has metido.

En el listener.ora:

…
LISTENER =
 (DESCRIPTION_LIST =
   (DESCRIPTION =
     (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
     (ADDRESS = (PROTOCOL = TCP)(HOST = orcl.dominio.lan)(PORT = 1521))
   )
 )
...

En el tnsnames.ora:

…
ORCL =
 (DESCRIPTION =
   (ADDRESS = (PROTOCOL = TCP)(HOST = orcl.dominio.lan)(PORT = 1521))
   (CONNECT_DATA =
     (SERVER = DEDICATED)
     (SERVICE_NAME = orcl.dominio.lan)
   )
 )
...

NOTA: si tienes más de una BBDD basta con que cambies el host de uno de ellos, si quieres asignar más de un host crea más entradas en el

3. Tiramos el Enterprise Manager

Vamos a la consola. Previamente establecemos en la consola estas variables de entorno. No hace falta ponerlas fijas si no queremos, ahora las necesitamos para que esto arranque:

c:\DOS\> set ORACLE_SID=orcl

c:\DOS\ > set ORACLE_UNQNAME=orcl

c:\DOS\> set ORACLE_HOSTNAME=orcl.dominio.lan

Y ahora lanzamos este comando para tirar el Enterprise Manager

c:\> emca -deconfig dbcontrol db -repos drop

Esto inicia un asistente en el que indicamos SID y contraseñas y sigue para adelante.

Se supone que elimina el usuario SYSMAN. Si no fuera así, tenemos que hacerlo a mano ejecutando estas sentencias:

DROP USER sysman CASCADE;

DROP PUBLIC SYNONYM setemviewusercontext;

DROP ROLE mgmt_user;

DROP PUBLIC SYNONYM mgmt_target_blackouts;

DROP USER mgmt_view;

4. Regeneramos el Enterprise Manager

Usando la misma sesión de antes ejecutamos:

c:\DOS\> emca -config dbcontrol db -repos create

Eso inicia un asistente como el anterior. Al cabo de unos minutos, nos mostrará la URL del Enterprise Manager. Asegúrate de que tu navegador no va a un proxy o añade las excepciones necesarias si es preciso. Ya podrás entrar en tu EM.

¿No puedes entrar tampoco? ¿Te ha dado algún error? Una nota: debes ser Administrador de sistema para hacerlo. Y otra cosa importante. El comando anterior, en caso de errores genera unos logs y además te indica dónde están. Ábrelos y ahí tendrás la explicación del problema que ha encontrado.

]]>
http://www.pello.info/index.php/blog/arreglar-e-iniciar-el-oracle-enterprise-manager
Errores frecuentes en aplicaciones Struts2 con Eclipse y Tomcat http://www.pello.info/index.php/blog/errores-frecuentes-en-aplicaciones-struts2-con-eclipse-y-tomcat http://www.pello.info/index.php/blog/errores-frecuentes-en-aplicaciones-struts2-con-eclipse-y-tomcat 2013-11-01 01:44:50 pelloxabier http://www.pello.info/index.php/blog/errores-frecuentes-en-aplicaciones-struts2-con-eclipse-y-tomcat Introducción

¿Tu aplicación struts2 falla?

¿Falla eclipse?

¿Ni si quiera arranca el tomcat o te está vomitando toda la stacktrace, toda la pila de llamadas erróneas por la consola?

Antes de echarse a llorar, desesperarse, increpar al proyecto apache, al profesor debes asegurarte de unos mínimos:

  • Tu proyecto no tiene errores de compilación
  • Tus clases y jsps no tienen ni un solo error.
  • Los ficheros XML no tienen ni un solo error.
  • No has confundido mayúsculas/minúsculas
Cómo revisar la consola

Cuando en la consola veas un montón de errores encadenados que no cunda el pánico. En java un simple error puede mostrar toda una ristra de errores que en realidad no es más que un volcado de llamadas que fallan en cadena, no porque sea especialmente grave.

Simplemente sube hacia arriba y observa dónde comienza el error. En algún punto te dirá que tienes un error en una clase tuya en una línea concreta. No es un error de compilación, es simplemente que en ese punto se ha desencadenado un error: no encuentra un fichero, no accede a la red, no encuentra una propiedad, algo es nulo…

Debes corregir ese error en esa clase o entender porqué ocurre, pero no te dejes agobiar por las 200 y pico líneas de Exception.

Error 404

Parece que no encuentra los contenidos, ni las acciones struts ni las jsp ni nada. Y lo peor es que algo que antes funcionaba ahora no. Primero asegúrate de que realmente el recurso al que quieres acceder existe. Obvio.

-> Solución: revisar

Revisa la consola porque tu proyecto tiene un error, y ahí se está explicando el porqué. Un fallo en un el struts.xml, una clase action que no existe, etc.. GOTO introducción.

Proyecto erróneo o con exclamación

Puede que al mover un proyecto de un lado para otro tengas problemas porque está configurado para otro JDK, o las librerías de tomcat no están en el mismo sitio, etc… A veces incluso deja de reconocer las clases y librerías básicas (String, java.util.*) o las librerías de tomcat (HttpServer, Session, ...). Debes :

->Solución: verificar el buildpath

Si hay algo incorrecto al entrar en la pestaña libraries del buildpath debieras ver alguna de ellas en rojo o una nota que dice (Unbound). Quita esa librería y añadela otra vez.

En el caso del JRE: debes añadir una library de JRE y asociar la de tu sistema.

En el caso de Tomcat: debes añadir una library de “Server Runtime” y seleccionar la de tomcat.

No encuentra action

Puede que nos salte un error en la consola tan grande como este:

Caused by: Unable to load configuration. - action - file:/C:/Users/Trabajo/Desktop/Trabajos/Pello/Sistemas%20de%20gestión%20Empresarial/Eclipse/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Tulebox/WEB-INF/classes/struts.xml:22:50
at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:70)
at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:446)
at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:490)
... 15 more
Caused by: Action class [info.fer.dice.Dice] not found - action - file:/C:/Users/Trabajo/Desktop/Trabajos/Pello/Sistemas%20de%20gestión%20Empresarial/Eclipse/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Tulebox/WEB-INF/classes/struts.xml:22:50

-> Solución: verificar paquetes, directorios y acciones

En ese caso debemos revisar el fichero struts.xml o el que esté incluyendo a través de la directiva Seguramente estamos haciendo una referencia a una acción cuya clase no está en la ruta correcta. Verifica que se corresponde el nombre del paquete con la ruta de directorios. Es decir,si la clase es SuperAction si el package de la clase es:

package org.cuatrovientos.struts2.example;

Entonces la clase debe encontrarse en el directorio

src > org > cuatrovientos > struts2 > example > SuperAction

Y en el action debe poner lo siguiente:

Deben coindicir si no dará error de Action no encontrada.

Cambio algo y sigue fallando lo mismo

Muchas veces corriges un error y el error persiste. O lo que es peor, algo que funcionaba, cambias alguna tontería y deja de arrancar. Parece ser que a veces el tomcat se queda pinzado, o por mucho que ejecutes el proyecto en el servidor te está ejecutando una versión vieja.

->Solución: vacía el Tomcat

Para asegurarte de que el proyecto que ejecutas es el bueno, saca todos los proyectos de tomcat. En la pestaña servidores, despliega el tomcat y quítale los proyectos, al menos el que quieres ejecutar. si ese proyecto viene de un copy paste de otro quita todos.

Ahora ejecuta de nuevo y lo harás con la última versión.

Tomcat no arranca
Tomcat logo

O Tomcat encountered a problema y resulta que no es capaz de iniciarse y no puedes iniciar la aplicación. Puede deberse a dos razones.

  1. Hay otra instancia de tomcat en marcha. Por ejemplo la del XAMPP. Hay que pararla o hacer que eclipse se ejecute en ella.
  2. Tomcat no es capaz de reiniciarse.
->Solución: parar y reiniciar

Por si acaso cárgate todos los proyectos que hay en el tomcat (pestaña servers, desplegar el tomcat y quitar todos), y luego detén el servidor. Ahora vuelve a ejecutar la aplicación y lo hará con más garantías de éxito.

... and greetz for u ;)]]>
Introducción

¿Tu aplicación struts2 falla?

¿Falla eclipse?

¿Ni si quiera arranca el tomcat o te está vomitando toda la stacktrace, toda la pila de llamadas erróneas por la consola?

Antes de echarse a llorar, desesperarse, increpar al proyecto apache, al profesor debes asegurarte de unos mínimos:

  • Tu proyecto no tiene errores de compilación
  • Tus clases y jsps no tienen ni un solo error.
  • Los ficheros XML no tienen ni un solo error.
  • No has confundido mayúsculas/minúsculas
Cómo revisar la consola

Cuando en la consola veas un montón de errores encadenados que no cunda el pánico. En java un simple error puede mostrar toda una ristra de errores que en realidad no es más que un volcado de llamadas que fallan en cadena, no porque sea especialmente grave.

Simplemente sube hacia arriba y observa dónde comienza el error. En algún punto te dirá que tienes un error en una clase tuya en una línea concreta. No es un error de compilación, es simplemente que en ese punto se ha desencadenado un error: no encuentra un fichero, no accede a la red, no encuentra una propiedad, algo es nulo…

Debes corregir ese error en esa clase o entender porqué ocurre, pero no te dejes agobiar por las 200 y pico líneas de Exception.

Error 404

Parece que no encuentra los contenidos, ni las acciones struts ni las jsp ni nada. Y lo peor es que algo que antes funcionaba ahora no. Primero asegúrate de que realmente el recurso al que quieres acceder existe. Obvio.

-> Solución: revisar

Revisa la consola porque tu proyecto tiene un error, y ahí se está explicando el porqué. Un fallo en un el struts.xml, una clase action que no existe, etc.. GOTO introducción.

Proyecto erróneo o con exclamación

Puede que al mover un proyecto de un lado para otro tengas problemas porque está configurado para otro JDK, o las librerías de tomcat no están en el mismo sitio, etc… A veces incluso deja de reconocer las clases y librerías básicas (String, java.util.*) o las librerías de tomcat (HttpServer, Session, ...). Debes :

->Solución: verificar el buildpath

Si hay algo incorrecto al entrar en la pestaña libraries del buildpath debieras ver alguna de ellas en rojo o una nota que dice (Unbound). Quita esa librería y añadela otra vez.

En el caso del JRE: debes añadir una library de JRE y asociar la de tu sistema.

En el caso de Tomcat: debes añadir una library de “Server Runtime” y seleccionar la de tomcat.

No encuentra action

Puede que nos salte un error en la consola tan grande como este:

Caused by: Unable to load configuration. - action - file:/C:/Users/Trabajo/Desktop/Trabajos/Pello/Sistemas%20de%20gestión%20Empresarial/Eclipse/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Tulebox/WEB-INF/classes/struts.xml:22:50
at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:70)
at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:446)
at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:490)
... 15 more
Caused by: Action class [info.fer.dice.Dice] not found - action - file:/C:/Users/Trabajo/Desktop/Trabajos/Pello/Sistemas%20de%20gestión%20Empresarial/Eclipse/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Tulebox/WEB-INF/classes/struts.xml:22:50

-> Solución: verificar paquetes, directorios y acciones

En ese caso debemos revisar el fichero struts.xml o el que esté incluyendo a través de la directiva Seguramente estamos haciendo una referencia a una acción cuya clase no está en la ruta correcta. Verifica que se corresponde el nombre del paquete con la ruta de directorios. Es decir,si la clase es SuperAction si el package de la clase es:

package org.cuatrovientos.struts2.example;

Entonces la clase debe encontrarse en el directorio

src > org > cuatrovientos > struts2 > example > SuperAction

Y en el action debe poner lo siguiente:

Deben coindicir si no dará error de Action no encontrada.

Cambio algo y sigue fallando lo mismo

Muchas veces corriges un error y el error persiste. O lo que es peor, algo que funcionaba, cambias alguna tontería y deja de arrancar. Parece ser que a veces el tomcat se queda pinzado, o por mucho que ejecutes el proyecto en el servidor te está ejecutando una versión vieja.

->Solución: vacía el Tomcat

Para asegurarte de que el proyecto que ejecutas es el bueno, saca todos los proyectos de tomcat. En la pestaña servidores, despliega el tomcat y quítale los proyectos, al menos el que quieres ejecutar. si ese proyecto viene de un copy paste de otro quita todos.

Ahora ejecuta de nuevo y lo harás con la última versión.

Tomcat no arranca
Tomcat logo

O Tomcat encountered a problema y resulta que no es capaz de iniciarse y no puedes iniciar la aplicación. Puede deberse a dos razones.

  1. Hay otra instancia de tomcat en marcha. Por ejemplo la del XAMPP. Hay que pararla o hacer que eclipse se ejecute en ella.
  2. Tomcat no es capaz de reiniciarse.
->Solución: parar y reiniciar

Por si acaso cárgate todos los proyectos que hay en el tomcat (pestaña servers, desplegar el tomcat y quitar todos), y luego detén el servidor. Ahora vuelve a ejecutar la aplicación y lo hará con más garantías de éxito.

... and greetz for u ;)]]>
http://www.pello.info/index.php/blog/errores-frecuentes-en-aplicaciones-struts2-con-eclipse-y-tomcat
Interfaz Metro y Shortcuts en Windows 2012 http://www.pello.info/index.php/blog/interfaz-metro-y-shortcuts-en-windows-2012 http://www.pello.info/index.php/blog/interfaz-metro-y-shortcuts-en-windows-2012 2013-08-31 21:56:26 pelloxabier http://www.pello.info/index.php/blog/interfaz-metro-y-shortcuts-en-windows-2012 Métodos abreviados

Algunas cabezas pensantes le han dado una vuelta al interfaz gráfico de las últimas versiones de Windows. Dida lo que diga el Vaticano el purgatorio y el infierno existen y debe ser el destino para los creadores de Metro, que es como se llama el interfaz que aparece ahora en al pulsar la tecla windows. Aquí dejaré unas pautas para poder sobrevivir. Pese a que existen herramientas para quitarlo, para tener un inicio normal, etc… creo que no queda más remedio que acostumbrarse porque no es la primera vez que introducen un cambio en el la forma de trabajar y no es posible empeñarse en tener siempre lo mismo.

Aparte de eso, Windows sigue manteniendo los shortcuts o métodos abreviados para agilizar el uso del sistema. Conviene saberlas ya que además de ser útiles siempre dan una imagen de que controlas. Andar arrastrando el ratón por la pantalla es muy luser, y cualquier informático que se precie debiera poder arreglarse en un Windows sin ratón (en modo ninja). Muchas de las combinaciones son bien conocidas. Estas las he probado en un Windows 2012, en un Windows 8 seguramente habrá más opciones en metro, para compartir y esas cosas sociales.

  • Win: muestra el interfaz metro. Si vuelves a pulsar Win, sales.
  • Space: en el interfaz metro abre opciones y da un enlace a todos los programas. Con el botón derecho del ratón también sale ese enlace.
  • Esc: sales del interfaz metro
  • Win + escribir algo: busca el programa que coincida con lo que escribes: cmd, notepad, ...
  • Win + c: importante si quieres APAGAR el equipo o acceder a la configuración.
  • Win + i: te lleva a la configuración
  • Win + f: te lleva a la pantalla de búsqueda de ficheros
  • Win + q: pantalla de búsqueda de aplicaciones y muestra todos los programas
  • Win + w: te lleva a la búsqueda de configuraciones
  • Win + x: muestra el nuevo menú de inicio
  • Win + e: la clásica, muestra un explorador de Windows, unidades, carpetas,...
  • Win + d: muestra en el escritorio
  • Win + r: ejecutar programa
  • Win + u: muestra centro de accesibilidad
  • Win + p: opciones para segunda pantalla
  • Win + t: se mueve entre las ventanas abiertas de la barra de tareas, enter para ejecutar
  • Win + l: lock, bloquea la pantalla
  • Win + Pause/Break: muestra las propiedades del sistema.
  • Win + Número: pasa a primer plano la aplicación, según el orden en que estén
  • Win + PrtSc: te guarda un pantallazo en Imágenes.
  • Win + m: minimiza todas las ventanas
  • Win + Arriba: maximiza la ventana.
  • Win + Abajo: minimiza la ventana.
  • Win + Izq: desplaza la ventana abierta a la izquierda.
  • Win + Der: desplaza la ventana abierta a la derecha.
  • Win + Space: cambia el idioma del teclado
  • Win + Enter: inicia el narrador
  • Win + +: aumenta con la lupa
  • Win + - : disminuye el tamaño con la lupa
  • Win + Esc: sale del magnificador
  • Ctrl + Mayus + Esc: Administrador de tareas
  • Shift + Supr: elimina un fichero/directorio sin dejarlo en papelera. Pide confirmación.
  • Alt + Enter: muestra propiedades de un fichero seleccionado
  • Alt + Der: en un Explorador de ficheros se mueve a la siguiente carpeta
  • Alt + Izq: en un Explorador de ficheros se mueve a la carpeta anterior
  • Alt + Arriba: en un Explorador de ficheros se mueve a la carpeta de nivel superior
  • Alt + Tab: cambiar de ventana, siempre para ocultarle algo a alguien ;)
  • Alt + Mayus + Tab: cambiar de ventana en orden inverso
  • Ctrl + Alt + Sup: si no lo sabes también irás al infierno, a un nivel lleno de usuarios a los que les tendrás que reinstalar el XP hasta el fin de los tiempos.

No sé si será cosa mía o que pero la tecla de pantallazos no tiene efecto alguno en Windows 2012. Por eso saber lo del Windows + PrtSc, está bien. aparte de eso, se supone que se podía sacar un pantallazo de la ventana actual con Alt + PrtSc, pero en 2012 no sale (No, pulsando Win + Alt + PrtSc tampoco)

Me ha hecho gracia ver esta imagen:

Promoción de Ubuntu

Los amigos de Ubuntu también pueden enseñarte mil nuevas formas de dolor con su interfaz Unity,

]]>
Métodos abreviados

Algunas cabezas pensantes le han dado una vuelta al interfaz gráfico de las últimas versiones de Windows. Dida lo que diga el Vaticano el purgatorio y el infierno existen y debe ser el destino para los creadores de Metro, que es como se llama el interfaz que aparece ahora en al pulsar la tecla windows. Aquí dejaré unas pautas para poder sobrevivir. Pese a que existen herramientas para quitarlo, para tener un inicio normal, etc… creo que no queda más remedio que acostumbrarse porque no es la primera vez que introducen un cambio en el la forma de trabajar y no es posible empeñarse en tener siempre lo mismo.

Aparte de eso, Windows sigue manteniendo los shortcuts o métodos abreviados para agilizar el uso del sistema. Conviene saberlas ya que además de ser útiles siempre dan una imagen de que controlas. Andar arrastrando el ratón por la pantalla es muy luser, y cualquier informático que se precie debiera poder arreglarse en un Windows sin ratón (en modo ninja). Muchas de las combinaciones son bien conocidas. Estas las he probado en un Windows 2012, en un Windows 8 seguramente habrá más opciones en metro, para compartir y esas cosas sociales.

  • Win: muestra el interfaz metro. Si vuelves a pulsar Win, sales.
  • Space: en el interfaz metro abre opciones y da un enlace a todos los programas. Con el botón derecho del ratón también sale ese enlace.
  • Esc: sales del interfaz metro
  • Win + escribir algo: busca el programa que coincida con lo que escribes: cmd, notepad, ...
  • Win + c: importante si quieres APAGAR el equipo o acceder a la configuración.
  • Win + i: te lleva a la configuración
  • Win + f: te lleva a la pantalla de búsqueda de ficheros
  • Win + q: pantalla de búsqueda de aplicaciones y muestra todos los programas
  • Win + w: te lleva a la búsqueda de configuraciones
  • Win + x: muestra el nuevo menú de inicio
  • Win + e: la clásica, muestra un explorador de Windows, unidades, carpetas,...
  • Win + d: muestra en el escritorio
  • Win + r: ejecutar programa
  • Win + u: muestra centro de accesibilidad
  • Win + p: opciones para segunda pantalla
  • Win + t: se mueve entre las ventanas abiertas de la barra de tareas, enter para ejecutar
  • Win + l: lock, bloquea la pantalla
  • Win + Pause/Break: muestra las propiedades del sistema.
  • Win + Número: pasa a primer plano la aplicación, según el orden en que estén
  • Win + PrtSc: te guarda un pantallazo en Imágenes.
  • Win + m: minimiza todas las ventanas
  • Win + Arriba: maximiza la ventana.
  • Win + Abajo: minimiza la ventana.
  • Win + Izq: desplaza la ventana abierta a la izquierda.
  • Win + Der: desplaza la ventana abierta a la derecha.
  • Win + Space: cambia el idioma del teclado
  • Win + Enter: inicia el narrador
  • Win + +: aumenta con la lupa
  • Win + - : disminuye el tamaño con la lupa
  • Win + Esc: sale del magnificador
  • Ctrl + Mayus + Esc: Administrador de tareas
  • Shift + Supr: elimina un fichero/directorio sin dejarlo en papelera. Pide confirmación.
  • Alt + Enter: muestra propiedades de un fichero seleccionado
  • Alt + Der: en un Explorador de ficheros se mueve a la siguiente carpeta
  • Alt + Izq: en un Explorador de ficheros se mueve a la carpeta anterior
  • Alt + Arriba: en un Explorador de ficheros se mueve a la carpeta de nivel superior
  • Alt + Tab: cambiar de ventana, siempre para ocultarle algo a alguien ;)
  • Alt + Mayus + Tab: cambiar de ventana en orden inverso
  • Ctrl + Alt + Sup: si no lo sabes también irás al infierno, a un nivel lleno de usuarios a los que les tendrás que reinstalar el XP hasta el fin de los tiempos.

No sé si será cosa mía o que pero la tecla de pantallazos no tiene efecto alguno en Windows 2012. Por eso saber lo del Windows + PrtSc, está bien. aparte de eso, se supone que se podía sacar un pantallazo de la ventana actual con Alt + PrtSc, pero en 2012 no sale (No, pulsando Win + Alt + PrtSc tampoco)

Me ha hecho gracia ver esta imagen:

Promoción de Ubuntu

Los amigos de Ubuntu también pueden enseñarte mil nuevas formas de dolor con su interfaz Unity,

]]>
http://www.pello.info/index.php/blog/interfaz-metro-y-shortcuts-en-windows-2012
Montar un laboratorio con máquinas virtuales en un host http://www.pello.info/index.php/blog/montar-un-laboratorio-con-maquinas-virtuales-en-un-host http://www.pello.info/index.php/blog/montar-un-laboratorio-con-maquinas-virtuales-en-un-host 2013-08-31 00:50:13 pelloxabier http://www.pello.info/index.php/blog/montar-un-laboratorio-con-maquinas-virtuales-en-un-host Supongamos que queremos montar un laboratorio de máquinas virtuales para jugar con servidores y clientes. Varias máquinas virtuales que queremos:
  • que sean visibles desde el host o equipo físico,
  • que sean visibles entre ellas y
  • que además puedan salir al exterior a través del equipo físico. Y es más,
  • queremos que esas máquinas virtuales tengan IP fija ya que al ser servidores no queremos que las IPs bailen

Y Vamos a suponer que tenemos el siguiente escenario:

Un equipo físico conectado a un router por DHCP, cuya ip es 192.168.0.1 y cuyas asignaciones de ips dinámicas son de la red 192.168.0.0/24, con el VMWare player instalado. En VMWare Player por defecto se crea dos interfaces de red VMnet1 como Host-only y VMnet8 para hacer NAT Por defecto también VMnet1 y VMnet8 crean su propio servidor DHCP y si conectamos los interfaces de red de las máquinas virtuales en esos modos (host-only o nat) y en el sistema operativo virtual el interface usa DHCP, entonces tomará esas direcciones.

¿Qué configuración debemos especificar en el adaptador de red físico, en los dos que genera vmware y en los adaptadores de las máquinas virtuales?

Si no hacemos nada, por defecto VMWare nos proporciona una tarjeta de red que utilizará NAT. En un entorno con DHCP en la red física la máquina virtual VMWare lo que hará será solicitar una IP al servidor DHCP. El problema añadido es que queremos EVITAR eso porque vamos a suponer que no tenemos muchas direcciones DHCP libres para asignar. Veamos las opciones:

Los tipos de conexión que ofrecen los interfaces de red VMWare son:

  • Bridging: conecta el interfaz de red de la máquina virtual a la red física. Directamente.
  • Host-only: crea una red interna entre VM
  • Nat: la máquina virtual (o varias de ellas) comparten la IP del host (la máquina física) Puedes quitar el DHCP que se asigna y crear una red entre el host y las máquinas virtuales y se verán entre sí. Esto es lo que vamos a probar en este caso.
El -oculto- configurador de redes de VMWare

Lo que necesitamos es poder configurar esos interfaces virtuales de VMWare, ¿pero cómo? Si estás usando VMWare player por defecto no te saldrá el configurador de interfaces de red VMWare, así que para configurar los servidores DHCP de los interfaces tenemos que hacer la siguiente cosa: Ir a la carpeta de VMWare:


cd C:\Program Files (x86)\VMware\VMware Player>

Y ejecutar lo siguiente:


rundll32.exe vmnetui.dll VMNetUI_ShowStandalone

Eso ejecutará el configurador. Según tu versión del player esto puede variar, así que tendrás que ver artículos como este: http://rednectar.net/2011/07/20/finding-vmnetcfg-exe-in-vmware-player-3-1-4/ o buscar en google por tu caso concreto.

Este es el aspecto del configurador de interfaces de VMWare y ahí es donde podremos meter mano al VMNet8:

El configurador de redes de VMWare

¿Y qué vamos a hacer ahí? Lo primero quitar el DHCP en el caso del NAT. Vamos a configurar que está en una red 192.168.42.0/24 y vamos a hacer una cosa curiosa. Al adaptador VMNet8 le asignaremos 192.168.42.1 con gateway 192.168.42.2 en el configuración de nat diremos que el gateway es efectivamente 192.168.42.2. ¿quién es? pues aparentemente el propio host, la 42.2 no la verá el mismo pero las máquinas virtuales sí.

Detalles de la configuración NAT
Máquina virtual

Ahora en cada máquina virtual pondremos una IP fija de la red 192.168.42.0/24:


ip: 192.168.42.10

máscara: 255.255.255.0

gateway: 192.168.42.2

dns: : 192.168.42.2

Y con eso conseguiremos los objetivos marcados: que se vean entre las virtuales, que se vean con el host y que las virtuales puedan salir a internet a través del host. Nota: para comprobar esa visibilidad he utilizado pings. Si hubieramos usado el modo Host-only conseguiriamos lo mismo salvo la salida a internet. Todas las máquinas eran windows 2012 server y para que el ping respondiera les he bajado el firewall hasta los tobillos a todos, no me gusta pero...

]]>
Supongamos que queremos montar un laboratorio de máquinas virtuales para jugar con servidores y clientes. Varias máquinas virtuales que queremos:
  • que sean visibles desde el host o equipo físico,
  • que sean visibles entre ellas y
  • que además puedan salir al exterior a través del equipo físico. Y es más,
  • queremos que esas máquinas virtuales tengan IP fija ya que al ser servidores no queremos que las IPs bailen

Y Vamos a suponer que tenemos el siguiente escenario:

Un equipo físico conectado a un router por DHCP, cuya ip es 192.168.0.1 y cuyas asignaciones de ips dinámicas son de la red 192.168.0.0/24, con el VMWare player instalado. En VMWare Player por defecto se crea dos interfaces de red VMnet1 como Host-only y VMnet8 para hacer NAT Por defecto también VMnet1 y VMnet8 crean su propio servidor DHCP y si conectamos los interfaces de red de las máquinas virtuales en esos modos (host-only o nat) y en el sistema operativo virtual el interface usa DHCP, entonces tomará esas direcciones.

¿Qué configuración debemos especificar en el adaptador de red físico, en los dos que genera vmware y en los adaptadores de las máquinas virtuales?

Si no hacemos nada, por defecto VMWare nos proporciona una tarjeta de red que utilizará NAT. En un entorno con DHCP en la red física la máquina virtual VMWare lo que hará será solicitar una IP al servidor DHCP. El problema añadido es que queremos EVITAR eso porque vamos a suponer que no tenemos muchas direcciones DHCP libres para asignar. Veamos las opciones:

Los tipos de conexión que ofrecen los interfaces de red VMWare son:

  • Bridging: conecta el interfaz de red de la máquina virtual a la red física. Directamente.
  • Host-only: crea una red interna entre VM
  • Nat: la máquina virtual (o varias de ellas) comparten la IP del host (la máquina física) Puedes quitar el DHCP que se asigna y crear una red entre el host y las máquinas virtuales y se verán entre sí. Esto es lo que vamos a probar en este caso.
El -oculto- configurador de redes de VMWare

Lo que necesitamos es poder configurar esos interfaces virtuales de VMWare, ¿pero cómo? Si estás usando VMWare player por defecto no te saldrá el configurador de interfaces de red VMWare, así que para configurar los servidores DHCP de los interfaces tenemos que hacer la siguiente cosa: Ir a la carpeta de VMWare:


cd C:\Program Files (x86)\VMware\VMware Player>

Y ejecutar lo siguiente:


rundll32.exe vmnetui.dll VMNetUI_ShowStandalone

Eso ejecutará el configurador. Según tu versión del player esto puede variar, así que tendrás que ver artículos como este: http://rednectar.net/2011/07/20/finding-vmnetcfg-exe-in-vmware-player-3-1-4/ o buscar en google por tu caso concreto.

Este es el aspecto del configurador de interfaces de VMWare y ahí es donde podremos meter mano al VMNet8:

El configurador de redes de VMWare

¿Y qué vamos a hacer ahí? Lo primero quitar el DHCP en el caso del NAT. Vamos a configurar que está en una red 192.168.42.0/24 y vamos a hacer una cosa curiosa. Al adaptador VMNet8 le asignaremos 192.168.42.1 con gateway 192.168.42.2 en el configuración de nat diremos que el gateway es efectivamente 192.168.42.2. ¿quién es? pues aparentemente el propio host, la 42.2 no la verá el mismo pero las máquinas virtuales sí.

Detalles de la configuración NAT
Máquina virtual

Ahora en cada máquina virtual pondremos una IP fija de la red 192.168.42.0/24:


ip: 192.168.42.10

máscara: 255.255.255.0

gateway: 192.168.42.2

dns: : 192.168.42.2

Y con eso conseguiremos los objetivos marcados: que se vean entre las virtuales, que se vean con el host y que las virtuales puedan salir a internet a través del host. Nota: para comprobar esa visibilidad he utilizado pings. Si hubieramos usado el modo Host-only conseguiriamos lo mismo salvo la salida a internet. Todas las máquinas eran windows 2012 server y para que el ping respondiera les he bajado el firewall hasta los tobillos a todos, no me gusta pero...

]]>
http://www.pello.info/index.php/blog/montar-un-laboratorio-con-maquinas-virtuales-en-un-host