Wikipedia

Resultados de la b煤squeda

viernes, 3 de diciembre de 2021

Handling dates in Spring: The right way

In this post I want to show you what — in my opinion —  is a nice way to handle dates within your Spring Boot application. Suitable both for business needs as well as for unit testing.

Usually we find situations in which dates are spawned simply with LocalDateTime.now() or — to make things worse  using the old API new Date(). This makes testing difficult since there's no easy way to control these scenarios for unit or integration testing.

A better approach would be to relay on a utility class in order to give the user the representation of what now means in certain context. Then again, we need either to do some obscure work to handle static methods in unit test — if you're wondering, there are several frameworks, being powermock the most known  or provide the functionality in that class for that purpose. Which in turn could lead to a usage of a test method — God forbids — within production code!

I would give you a clue: There's a mechanism that you're been using for quite a long time that's really handy for this situation... I think you might have guessed by now. YES! it's dependency injection!

Here's a simple class definition to show this approach:


In order for to be fully operational within a Spring context, you'll need to create the following configuration as well:



As you may have guessed, this Spring component will allow us to inject in every other component that we need to get what is the current date. It will also allow us to mock its methods easily with tools like Mockito.

In order to illustrate this, let's imagine that we need to code a feature that needs to validate if a credit card is expired or not. It should also tell us if the card is soon to expire if we're within the actual expiration month. To make this thing more interesting I will use TDD to build the code piece by piece.

Now, for simplicity this will be the class definition for the card:

public class Card {
private String cardholderName;
private String cardNumber;
private LocalDate expirationDate;
}
Let's create our CardExpirationService that will be the responsible for the logic regarding the expiration. After that, let's create the test class as well with the help of an IDE.

We can already start building the first scenario. I'm going to start with a non expired card. We create a non expired card, that is, a card that has an expiration date greater than a month from what we consider "now". Remember, we're doing this in a TDD way, so here's as far as I can get for my test code:

Let the IDE create the method for me so I can go back to the test again. And write the necessary assertion. Lest assume we want to get a "VALID" string for this scenario. The final test looks like this:
@Test
void shouldGetValidCard() {
LocalDate threeMonthsFromNow = LocalDate.now().plusMonths(3);
Card validCard = new Card(threeMonthsFromNow);

String result = cardExpirationService.validateExpiration(validCard);

Assertions.assertEquals("VALID", result);
}
No, if we run it, we'll get an error, of course, so it's time to move to the production code once again. Basically we'll check if the expiration date is in the future, so we write something like this:
public String validateExpiration(Card card) {

LocalDate today = LocalDate.now();
if (today.isBefore(card.getExpirationDate())) {
return "VALID";
}

return null;
}
Now, we run the test and we should have a neat green check! Let's write the next scenario. I'll choose the already expired scenario this time:
@Test
void shouldGetExpiredCard() {
LocalDate yesterday = LocalDate.now().minusDays(1);
Card expiredCard = new Card(yesterday);

String result = cardExpirationService.validateExpiration(expiredCard);

Assertions.assertEquals("EXPIRED", result);
}
Run this test and we should get an error again. It's time to go back to the production code and see what's wrong. The next obvious choice for us this time is to add an else clause and return from there. It should look similar to this:
public String validateExpiration(Card card) {

LocalDate today = LocalDate.now();
if (today.isBefore(card.getExpirationDate())) {
return "VALID";
} else {
return "EXPIRED";
}
}
And with no surprise, the tests are green again! Sweet! Now, let's tackle down the last scenario. A card that is soon to be expired:
@Test
void shouldGetSoonToBeExpiredCard() {
LocalDate oneDayBeforeEndOfMonth = LocalDate.now().plusMonths(1).minusDays(1);
Card soonToExpireCard = new Card(oneDayBeforeEndOfMonth);

String result = cardExpirationService.validateExpiration(soonToExpireCard);

Assertions.assertEquals("EXPIRES_SOON", result);
}
If we run the tests at this point we should get an error stating that:
Expected :EXPIRES_SOON
Actual :VALID
Time to go back to the production code and see what's wrong. So, for the time being, this particular case still represents a valid card. So we have to so something inside that branch. It may look like this:
public String validateExpiration(Card card) {

LocalDate today = LocalDate.now();
if (today.isBefore(card.getExpirationDate())) {
long daysToExpire = ChronoUnit.DAYS.between(today, card.getExpirationDate());
if (daysToExpire <= today.getMonth().maxLength()) {
return "EXPIRES_SOON";
}
return "VALID";
} else {
return "EXPIRED";
}
}
At this point all the tests shall pass. But so far we just covered an imaginary scenario that rarely ever happens in real life. What happens in reality is that we have to deploy this code within some other service possibly across multiple timezones. The integration test you write based on mocked data will start failing — when, all of a sudden, all cards are expired —. If we think about it, the class CardExpirationService somehow knows what day is it today, and that's not a responsibility of the class. Think of yourself, you just don't know what time is, do you? You go to your smartwatch — or a grandfather's clock— to exactly know what the time is. So let's do the same for this class. Let's give the chance to look at our controlled clock. The whole class should look like this:
public class CardExpirationService {

private final BusinessDateUtils businessDateUtils;

public CardExpirationService(BusinessDateUtils businessDateUtils) {
this.businessDateUtils = businessDateUtils;
}

public String validateExpiration(Card card) {

LocalDate today = businessDateUtils.getCurrentDate();
LocalDate expirationDate = card.getExpirationDate();

if (today.isBefore(expirationDate)) {
long daysToExpire = ChronoUnit.DAYS.between(today, expirationDate);
if (daysToExpire <= today.getMonth().maxLength()) {
return "EXPIRES_SOON";
}
return "VALID";
} else {
return "EXPIRED";
}
}
}
And we can perfectly control what now is from our unit test using a mocking framework, or, in this case — and for the sake of simplicity — I just wrote a custom implementation for the BusinessDateUtils interface. The test class should look like this:
class CardExpirationServiceTest {

private static final LocalDate now = LocalDate.of(2020, 4, 21);

private CardExpirationService cardExpirationService;

@BeforeEach
void setUp() {
BusinessDateUtils businessDateUtils = new TestBusinessDateUtils(now);

cardExpirationService = new CardExpirationService(businessDateUtils);
}

@Test
void shouldGetValidCard() {
LocalDate threeMonthsFromNow = now.plusMonths(3);
Card validCard = new Card(threeMonthsFromNow);

String result = cardExpirationService.validateExpiration(validCard);

Assertions.assertEquals("VALID", result);
}

@Test
void shouldGetExpiredCard() {
LocalDate yesterday = now.minusDays(1);
Card expiredCard = new Card(yesterday);

String result = cardExpirationService.validateExpiration(expiredCard);

Assertions.assertEquals("EXPIRED", result);
}

@Test
void shouldGetSoonToBeExpiredCard() {
LocalDate withinTheMonth = now.plusDays(3);
Card soonToExpireCard = new Card(withinTheMonth);

String result = cardExpirationService.validateExpiration(soonToExpireCard);

Assertions.assertEquals("EXPIRES_SOON", result);
}

}

As you can imagine, and with a little bit of Spring magic you can set a custom clock for your integration and/or unit tests with just a few lines of code 馃槃

And yes, of course, now that we have the unit tests in place we can add a few more scenarios for edge cases and do a little bit of refactor on the production code to make it cleaner 馃槈

Hope you find this useful and see you next time!


s谩bado, 27 de noviembre de 2021

Architecture diagrams made easy

When you're starting a new project it's crucial that you are able to understand quickly how the systems that you'll be working on connect to each other and the general idea behind their architecture. Then on a deeper level, you'll need to understand how the components of those systems works together.

A code generated container diagram

Often happens that they give you a general architecture diagram that's really neat but it doesn't tell you exactly what you need to know in order to be able to do your job.

Other times you have to implement or refactor some features that alter the way things are connected at the moment and you have to re-route them or connect to other systems.

On rare occasions, you start a brand new project in which you are responsible to define how the components of the particular software you're trying to build connects to one another.

Throughout the years I had the chance to experiment all of the aforementioned situations. In some of them I had more documentation at hand and in others... well... let's say that it had some room for improvement in that area.

At the time I was working for Southwest Airlines the diagrams (sequence, modules, etc) were made using WebSequenceDiagrams and/or Microsoft Visio. They looked really neat and everything. But there were a few problems from my point of view: 

  • When the diagrams were done then the cost of updating them was really high. You needed to copy the source file if it was in Visio and change them using drag & drop with the mouse. A hideous task for a software developer.
  • For some additional features it was necessary to have a premium account.
  • The tooling was different from the everyday one.
  • It was complicated to version them.
  • Collaboration was limited.
That's me making a fool of myself...
 

So when we had to design a new login feature I decided to investigate how can that be done better. I definitely was looking for a tool that you can write the code and it would create the diagrams from it (Just like WebSequenceDiagrams but with versioning and open source). That's when I found PlantUML.

By using that tool it was really easy to maintain architecture diagrams as they where evolving alongside the features or the new requirements that we need to implement. Building a sequence diagram to visualize how particular services should interact had become an enjoyable task for developers and we also had that versioned in our code repository. Even when I had to document a card it was really painless to write a few lines and render the diagram (a sequence diagram for instance) on it just with the use of your favourite IDE.

A few years later when moved to LATAM Airlines project they were using PlantUML as well but they made a huge improvement. On top of PlantUML they decided to use the C4 Model for modeling software architecture. That is exactly what I want to show you in this post.

At this point you may be willing to get your hands dirty and start writing those beautiful diagrams, don't you? Well, the wait is over!

The first thing we need to do is clone this repository so we can have all the templates for the C4 software architecture model as foundation. You may also want to take a look at the README now that you are at it 馃槈

git clone https://github.com/plantuml-stdlib/C4-PlantUML.git

Note: There's no need to clone the repo because you can use directly by importing the web file from your diagram files. Nonetheless I think it's a good idea to take a look at it and play around with the templates.

Let's create our own project folder to start working on it. For simplicity I will call it "diagrams". Create the folder right next to the downloaded repository one.

Now download the PlantUML executable into it by issuing the following command:

wget https://github.com/plantuml/plantuml/releases/download/v1.2021.14/plantuml-1.2021.14.jar
At this moment we can start by creating our first dummy diagram. Copy and paste the following snippet into a dummy.puml file:

 

Now with the following command we'll generate the awesome image file:

java -jar plantuml-1.2021.14.jar .

And after a few seconds you should see a file called "My_First_Diagram.png" in the same folder.

Example diagram
 
I'm feeling that you are starting to think some ways in which you cant start using it in your project by now...
 
If you're using IntelliJ or VS Code there are fantastic plugins that'll render this as you type the code. The plugin for IntelliJ can be found here.

The invitation to start making your own beautiful architecture diagrams by code has been made! I think that with a little bit of scripting you can start adding this diagrams along with your codebase so you'll always have your architecture diagrams clean and updated.

I hope you find this post useful and entertaining 馃榿
 
See you next time!

mi茅rcoles, 24 de noviembre de 2021

Moved to The Netherlands!

It's been seven years since I did my last post in this blog. It's a completely different world now! At least for me many things happened in between: I changed my job, got my engineering degree, got married and moved to The Netherlands!

The last topic is precisely what I want to talk about it in this post.

I'm gonna tell you a little bit of our history on why this movement.

A few years ago, we had the chance to buy really cheap flights and travel to Europe. Since we're from Argentina it was something we really like to do and one of a kind opportunity. I have to give the credits for this to my wonderful wife Roberta because she was the one pushing to find the tickets. I only said the words "buy them" while taking a bus to Buenos Aires during a business trip. We had to make the purchase within a few hours, not much time to decide!

One of the places we stayed at that time was Amsterdam. The moment we arrived at the city centre was a turning point for us. We looked at each other to say:
We have to live here one day!

A tour we took around the canals

Fast forwarding into recent days, we were struggling about what are we supposed to do with our life. Because we knew we wanted to live abroad and we also had a relocation to Chile that got stuck in between bureaucracy and covid restrictions... For that we had the feeling that we were going nowhere...


Enjoying the afternoon

One day my wife found a job posting in Linkedin about a company that offered relocation to The Netherlands. This awesome company is called WAES 馃槈. So I decided to give it a shot. I posted my resume and waited for the recruitment process.
After a few days I got a message requesting for a videocall, which of course I replied. After that nice interview, a coding challenge and a technical interview I was offered a contract with a relocation package for me and my wife! We couldn't believe it!!! Our dream was finally becoming a reality!


So since about a month ago we're happily living in The Netherlands!馃懌


That's it for now so stay tuned! I will create new posts about living here and the whole process I had to go through!

See you soon! Hope in less than seven years... 馃槣

In the meantime, take this cookie 馃榿

A cookie from Van Stapele Koekmakerij


viernes, 14 de noviembre de 2014

Monitoreo de aplicaciones Java con VisualVM

En esta ocaci贸n (y mientras hago la segunda parte del post de entorno de desarrollo) les voy a mostrar c贸mo monitorear aplicaciones java con una muy buena herramienta incluida en el JDK que se llama VisualVM.

El objetivo de hacer esto es poder obtener estad铆asticas de performance y poder detectar posibles problemas de antemano. Por ejemplo haber establecido una cantidad muy peque帽a de memoria heap o PermGen y que la aplicaci贸n falle miserablemente.


Est谩 de m谩s decir que necesitamos tener instalado el entorno de ejecucuci贸n de Java para nuestro S.O.

Si estamos en nuestra pc con RedHat/CentOS/Fedora ejecutamos el  siguiente comando:

$ sudo yum install visualvm

Luego buscamos el programa en nuestro men煤 de aplicaciones y lo ejecutamos.

Se nos presentar谩 la pantalla que figura m谩s arriba y podremos comenzar a monitorear nuestras aplicaciones java corriendo localmente (Ej, el propio VisualVM).

Now the fun stuff!

Vamos a abrir alguna aplicaci贸n Java. Para este ejemplo voy a abrir la IDE NetBeans 8.0.1 con algunos proyectos abiertos.

Volvemos al VisualVM y dentro del nodo local vemos el proceso de NetBeans. Hacemos doble clic para que comienze a mostrarnos los indicadores.

La primer pantalla que se nos presenta es "Overview":

Aqu铆 podremos ver el Id del proceso, los argumentos con los que se inicializ贸 esta VM, la versi贸n de la plataforma y las propiedades del sistema en la pesta帽a "System properties".

Exiten 4 pesta帽as m谩s: "Monitor", "Threads", "Sampler" y "Profiler".

Dentro de la pesta帽a Monitor podremos observar estad铆sticas de utilizaci贸n de memoria Heap y PermGen, de utilizaci贸n de CPU, la cantidad de clases cargadas y los hilos de  ejecuci贸n.

La siguiente pesta帽a "Monitor" es muy interesante:

Aqu铆 se presentan datos clave: La utilizaci贸n de CPU, tama帽o de memoria utilizada, cantidad de clases cargadas y los hilos de ejecuci贸n. Si por ejemplo  quisieramos ver si hemos establecido un buen l铆mite de espacio PermGen de memoria podr铆amos hacer clic en la pesta帽a PermGen y ver cu谩l es la utilizaci贸n de este espacio de memoria mientras nuestra aplicaci贸n se ejecuta.
Podemos forzar a que la JVM realice una recolecci贸n de basura con el bot贸n "Perform GC".

En la pesta帽a "Sampler" podemos almacenar datos de funcionamiento de nuestra aplicaci贸n para obtener estad铆sticas de performance sobre los distintos m贸dulos de nuestra aplicaci贸n.  Podremos hacerlos  sobre el uso de memoria y CPU.


Aqu铆 podemos incluso ver la performance de ejecuci贸n de un m茅todo determinado que ejecuta nuestra aplicaci贸n y as铆 poder detectar en d贸nde podr铆amos estar teniendo problemas de rendimiento.
Obviamente los resultados pueden exportarse para ser analizados m谩s en detalle con posterioridad.

Espero que les haya sido 煤til esta entrada y que lo disfruten! Hasta la pr贸xima!

jueves, 25 de septiembre de 2014

C贸mo montar un entorno de desarrollo Java (Parte 1)

Hola! Despu茅s de mucho tiempo sin subir nadas por fin tengo algo de tiempo para armar este tutorial que espero les sea de utilidad.

El tema que voy a tratar en esta ocaci贸n es como montar un entorno de desarrollo completo para nuestros desarrollos en Java.

El objetivo de esta gu铆a es mostrarles de la manera m谩s sencilla posible  como configurar e instalar las siguientes aplicaciones:
  • GIT
  • Nexus
  • Maven
  • Jenkins
  • GlassFish Application Server
Manos a la obra entonces! Configuremos ese entorno de desarrollo mediante el uso de aplicaciones de c贸digo abierto!


Vamos a partir del supuesto de que tenemos un PC servidor y luego uno o varios equipos clientes o de desarrollo. Vamos a instalar CentOS  7 en el servidor para poder configurar all铆 toda la infraestructura necesaria. No cubrir茅 la parte de la instalaci贸n de CentOS porque seguro ya lo saben hacer, y si no hay muchos tutoriales. La instalaci贸n es bastante sencilla.

En nuestro  servidor reci茅n instalado vamos a instalar mediante yum los paquetes del entorno de ejecuci贸n de Java y el JDK. Tambi茅n es necesario instalar el repositorio EPEL:

# wget http://dl.fedoraproject.org/pub/epel/beta/7/x86_64/epel-release-7-1.noarch.rpm
# yum install epel-release-7-1.noarch.rpm

Vayamonos empapandonos de conocimientos...

Qu茅 es Nexus?


Nexus es una herramienta que nos permite mantener un repositorio de componentes accesible en nuestro entorno de trabajo. Nos permitir谩 administrar y compartir los componentes que hayamos creado con todo nuestro equipo de desarrollo. Adem谩s actuar谩 como cach茅 de componentes de forma tal de descagar los componentes desde el repositorio central y luego hasta las pc de los desarrolladores por medio de la red local.

Antes que nada es conveniente que creemos un usuario dentro de nuestro CentOS para que sea el responsable de correr el proceso de nexus. Para ello invocaremos el siguiente mando para crear el usuario:

# useradd nexus
# passwd nexus

Escribimos una contrase帽a supersegura para el usuario y nos loguamos.
Ahora debemos descargar nexus oss del siguiente enlace:

http://www.sonatype.org/nexus/go

All铆 elegimos descargar el paquete TGZ. Al momento de este tutorial la version es 2.9.1
Ahora debemos tener un archivo nexus-<version>.tar.gz.
Lo descomprimirmos mediante el mando:

$ tar -zxvf nexus-2.9.1-02-bundle.tar.gz

Ahora tendremos una carpeta nexus-2.9.1-02 en la que est谩n los archivos necesarios para correr la aplicaci贸n y los archivos para configurarla.
Dentro de la careta "conf" se encuentra un archivo llamado nexus.properties en el cual podremos configurar el puerto en el cual se ejecute el servicio con la propiedad application-port.

Ahora bien, lo interesante ser铆a que el proceso se inicie con el sistema como servicio, para lo  cual vamos  a crear el siguiente script dentro de /etc/init.d/
#!/bin/bash
#
# nexus: Startup script for Nexus.
#
# chkconfig: 3 80 05
# description: Startup script for Nexus.
 
NEXUS_HOME=/home/nexus/nexus-2.9.1-02;
export NEXUS_HOME
 
NEXUS_OWNER=nexus;
export NEXUS_OWNER
 
start() {
echo -n "Starting Nexus: "
su $NEXUS_OWNER -c "$NEXUS_HOME/bin/nexus start"
sleep 2
echo "done"
}
 
stop() {
echo -n "Stopping Nexus: "
su $NEXUS_OWNER -c "$NEXUS_HOME/bin/nexus stop"
echo "done"
}
 
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
echo $"Usage: nexus {start|stop|restart}"
exit
esac

Le damos permisos de ejecuci贸n con:

# chmod +x /etc/init.d/nexus

Y finalmente lo agregamos  a los servicios de inicio con:

# chkconfig nexus on

Luego iniciamos el servicio:

# systemctl start nexus

Si ahora nos dirigimos a la siguiente direcci贸n:

http://<ip-server>:8081/nexus

Deveremos poder ver la siguiente pantalla:


Hasta ahora y si han seguido mis indicaciones al pi茅 de la letra estamos en condiciones de afirmar que tenemos nuestro nexus "up and running"!

Por defecto nexus viene configurado con 3 usuarios: anonymous, deployment y admin.
anonymous: tiene permisos de solo lectura
deployment: puede cargar nuevos componentes (los que creemos nosotros, veremos para que sirve esto m谩s adelante)
admin: puede leer y escribir sin restricciones

Pues bien, basta de ch谩chara, ahora vamos a enfocarnos en GIT:


Qu茅 es GIT?


GIT es un sistema de control de versiones distribuido creado por el famoso Linus Torvalds (no se si les suena ;) ). La diferencia es que lleva el  control de un repositorio local en cada equipo de desarrollador que luego es subido (push) al servidor central. Soporta los conceptos de branch y tags para identificar hitos o fases que va cumpliendo la aplicaci贸n que se est茅 versionando.
En t茅rminos generales un desarrollador se conecta al servidor hace un checkout (clone) del fuente del repositorio, hace algunos cambios, hace commit sobre su repositorio local  y luego hace un push para enviar sus cambios al servidor central de  forma tal que los dem谩s desarrolladores puedan realizar  un pull y obtener los 煤ltimos cambios.

Vamos a instalar lo siguiente en el equipo de desarrollador GIT:
# yum install -y git

En un d铆a normal un desarrollador modificar谩 y crear谩 nuevos archivos, luego realizar谩 un commit sobre su repositorio local y por 煤ltimo un push al repositorio remoto para que sus cambios est茅n disponibles para todos los usuarios.

Bueno, esto fue todo para la primera entrega, los espero la pr贸xima para terminar de configurar todo lo prometido!

Hasta la pr贸xima!

martes, 14 de mayo de 2013

Container Managed Security (JDBC Realm)

Bueno, ten铆a un poco colgado mi blog as铆 que decid铆 publicar este peque帽o tutorial sobre como manejar la seguridad en nuestras aplicaciones web mediante el contenedor de aplicaciones.

Cuando se trata de seguridad en la aplicaci贸n existen dos posibles caminos:
  1. Controlar la seguridad por nuestros propios medios ("a mano")
  2. Utilizar las funcionalidades provistas por el conenedor de aplicaciones para tal fin.
Siempre es recomendable elegir el segundo camino, puesto que expertos en seguridad han probado y dise帽ado las herramientas para proveer la seguridad en la aplicaci贸n. En s铆ntesis, para asegurar una aplicaci贸n lo que vamos a hacer es establecer usuarios y grupos de usuarios en un repositorio de seguridad del contenedor de aplicaciones.
La seguridad en una aplicaci贸n web se divide en la autentificaci贸n (proceso por el cual se verifica la identidad de un usuario) y la autorizaci贸n (proceso que determina si un usuario tiene acceso a un recurso o tarea particular cuando el usuario ya se encuentra autenticado). 
Asumiremos que en nuestra aplicaci贸n tendremos dos tipos de usuarios: los usuarios regulares (que podr谩n acceder a la parte /users/ del sitio) y los administradores (quienes adem谩s de poder acceder a la parte de usuarios tambi茅n podr谩n acceder a la parte de /admin/). Los usuarios que no se hayan autentificado solo podr谩n acceder a la parte p煤blica de la aplicaci贸n.

Lo que queremos hacer es que nuestra aplicaci贸n utilice el recurso JDBC para acceder a la informaci贸n de los usuarios y grupos.

Los "security realms" son colecciones de usuarios y grupos relacionados. Un usuario puede pertenecer a uno o m谩s grupos de seguridad y son 茅stos grupos los que definen qu茅 acciones pueden llevar a cabo los usuarios. Para el contenedor de aplicaciones el "realm" es interpretado como un string para identificar y obtener un nombre de usuario y una contrase帽a.
Para comenzar crearemos una base de datos con la siguiente estructura:
Tenemos entonces 3 tablas y una vista, el script para crearlas es el siguiente:

CREATE TABLE Grupos (

Id_Grupo INT(10) PRIMARY KEY,

Nombre_Grupo VARCHAR(30) NOT NULL,

Descripcion_Grupo VARCHAR(255)

);



CREATE TABLE Usuarios(

Id_Usuario INT(10) PRIMARY KEY,

LogIn VARCHAR(30) NOT NULL UNIQUE,

Nombre_Completo VARCHAR(60) NOT NULL,

password CHAR(64) NOT NULL 

);



CREATE TABLE Usuarios_X_Grupos (

Id_Usuario INT(10) NOT NULL FOREIGN KEY (Id_Usuario)

REFERENCES Usuarios(Id_Usuario) ON UPDATE NO ACTION ON DELETE NO ACTION,

Id_Grupo INT(10) NOT NULL FOREIGN KEY (Id_Grupo)

REFERENCES Grupos(Id_Grupo) ON UPDATE NO ACTION ON DELETE NO ACTION,

CONSTRAINT Usuarios_X_Grupos_PK PRIMARY KEY (Id_Usuarios,Id_Grupo)

);



CREATE VIEW V_Roles_Usuarios AS



SELECT  u.LogIn, u.password, g.Nombre_Grupo



 FROM Usuarios_X_Grupos ug



 INNER JOIN Usuarios u ON u.Id_Usuario = ug.Id_Usuario



 INNER JOIN Grupos g ON g.ID_Grupo =  ug.Id_Grupo; 



INSERT  INTO Grupos (Id_Grupo,Nombre_Grupo,Descripcion_Grupo) VALUES

  (1,'USER','Usuarios Regulares'),

  (2,'ADMIN','Usuarios de administraci贸n');

  

INSERT  INTO Usuarios(ID_Usuario,LogIn,Nombre_Completo,password) VALUES

  (1,'john','John','6e0b7076126a29d5dfcbd54835387b7b'), /*john123*/

  (2,'admin','ADMIN','21232f297a57a5a743894a0e4a801fc3'); /*admin*/
  

INSERT  INTO Usuarios_X_Grupos(Id_Usuario,ID_Grupo) VALUES (1,1),(2,1),(2,2);



Ya que tenemos la base de datos que va a almacenar nuestros datos de usuarios estamos listos para crear una conexi贸n a nuestra base de datos a trav茅s de la consola de administraci贸n de glassfish.

Para ingresar en la consola de administraci贸n de GlassFish se debe acceder a http://localhost:4848

Una vez dentro se debe ir a Resources/Connection Pools y luego hacer clic en New. Ingresamos el nombre y hacemos clic en next.

En el segundo paso dejamos todos los valores por defecto y hacemos clic en Finish.

Luego seleccionamos el pool de y hacemos clic en Additional Properties y en add properties, como en la figura:
Completamos los datos para poder conectarnos a la base de datos en los campos. Cuando hayamos terminado podemos hacer clic en el bot贸n Ping para ver si la conexi贸n fue configurada correctamente.
Si la configuraci贸n est谩 OK hacemos clic en JDBC Resources y luego en New.
El nombre JNDI va a ser el que se utilice en el "jdbc security realm" para obtener la conexi贸n a la base de datos. Colocamos el nombre que queramos y seleccionamos el pool de conexiones que hab铆amos creado.
  

Una vez que hayamos configurado todo lo anterior podremos configurar el JDBC realm. Vamos a Configuration/Security/Realms y hacemos clic en New.


Colocamos el nombre para este jdbc realm (este nombre ser谩 usado en el web.xml) y seleccionamos JDBCRealm en la lista de selecci贸n. Colocamos las propiedades como se muestran en la imagen.
El valor de JNDI debe ser igual al del JDBC Resource que creamos.

Lo interesante en este caso es que para "User Table" y para "Group Table" us茅 la vista "V_Roles_Usuarios" como valor de la propiedad. En esta vista se tienen los datos del usuario y del grupo juntos. La raz贸n por la cual no se usaron los nombres de las tablas correspondientes es porque glassfish asume que tanto en la tabla de usuarios como en la de grupos hay una columna que contiene el nombre de usuario y eso resultar铆a en datos duplicados.

Se pueden colocar las propiedades como se ve en la imagen y todas las dem谩s pueden ser dejadas en blanco.

Una vez definido el JDBC Realm necesitamos configurar nuestra aplicaci贸n. Toda la l贸gica de la autentificaci贸n ser谩 llevada a cabo por el servidor de aplicaci贸n, de esta forma solo deberemos hacer algunas modificaciones en los descriptores de despliegue para asegurar la aplicaci贸n, o sea, en web.xml y en sun-web.xml.
Agregamos lo siguiente al archivo web.xml:

<login-config>
    <auth-method>FORM</auth-method>
    <realm-name>jdbc-realm</realm-name>
    <form-login-config>
      <form-login-page>/faces/login.xhtml</form-login-page>
      <form-error-page>/faces/loginError.xhtml</form-error-page>
    </form-login-config>
    </login-config>

El elemento "login-config" define al m茅todo de autorizaci贸n para la aplicaci贸n (en este caso el form ser谩 mostrado al usuario para que se autentique) y el realm que ser谩 utilizado para la autorizaci贸n. Definimos tambi茅n las p谩ginas para el login y para el login incorrecto. Si el usuario intenta dirigirse a una url sin haberse autenticado antes, ser谩 redirigido a la pantalla de LogIn primero. Si la autenticaci贸n falla, se redireccionar谩 a la p谩gina loginError.

<security-constraint>
    <web-resource-collection>
      <web-resource-name>Admin user</web-resource-name>
      <url-pattern>/faces/admin/*</url-pattern>
      <http-method>GET</http-method>
          <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
      <role-name>ADMIN</role-name>
    </auth-constraint>
  </security-constraint>
  
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Admin user</web-resource-name>
      <url-pattern>/faces/users/*</url-pattern>
      <http-method>GET</http-method>
          <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
      <role-name>ADMIN</role-name>
      <role-name>USER</role-name>
    </auth-constraint>
  </security-constraint>

El elemento "security-constraint" define qui茅n tiene acceso a las p谩ginas que concuerdan con cierto patr贸n de URL. LOs roles admitidos para el acceso son definidos en este elemento.
Queremos que los usuarios administradores tengan acceso a los recursos dentro de /admin/*. Los usuarios regulares y administradores tienen acceso a los recursos dentro de /users/*.
Antes de que podamos autenticar satisfactoriamente a nuestros usuarios, debemos enlazar los roles de usuario definidos en el archivo web.xml con los grupos definidos en el realm. Hacemos esto mediante el archivo sun-web.xml.

<security-role-mapping>
    <role-name>ADMIN</role-name>
    <group-name>ADMIN</group-name>
  </security-role-mapping>
  <security-role-mapping>
    <role-name>USER</role-name>
    <group-name>USER</group-name>
  </security-role-mapping>

El archivo sun-web.xml puede tener uno o m谩s elementos. Cada uno de estos elementos por cada rol definido en el archivo web.xml
De esta manera, si un usuario ingresa una URL como la siguiente: "http://host/showcase/faces/users/users.xhtml" ser谩 redireccionado a la pantalla de login. El c贸digo para dicha pantalla se encuentra a continuaci贸n:

<h:body>
  <p>Login to access secure pages:</p>
  <form method="post" action="j_security_check">
    <h:panelGrid columns="2">
      <h:outputLabel for="j_username" value="Username" />
      <input type="text" name="j_username" />

      <h:outputLabel for="j_password" value="Password" />
      <input type="password" name="j_password" />

      <h:outputText value="" />
      <h:panelGrid columns="2">
        <input type="submit" name="submit" value="Login" />
        <h:button outcome="index" value="Cancel" />
      </h:panelGrid>
    </h:panelGrid>
  </form>
</h:body>
Es importante destacar que los atributos j_security_check, j_username and j_password son requeridos por la autentificaci贸n manejada por el contenedor y no se deben renombrar.
Luego de que se haya autenticado el usuario se redireccionar谩 a la url requerida. La p谩gina users tiene un simple enlace para desloguearse.

<h:body>
  <p>Welcome to user pages</p>
  <h:form>
    <h:commandButton action="#{authBackingBean.logout}" value="Logout" />
  </h:form>
</h:body> 
 
 
Y el bean que ejecuta el logout es:


@ManagedBean
@RequestScoped
public class AuthBackingBean {
  
  private static Logger log = Logger.getLogger(AuthBackingBean.class.getName());
  
  public String logout() {
    String result="/index?faces-redirect=true";
    
    FacesContext context = FacesContext.getCurrentInstance();
    HttpServletRequest request = (HttpServletRequest)context.getExternalContext().getRequest();
    
    try {
      request.logout();
    } catch (ServletException e) {
      log.log(Level.SEVERE, "Failed to logout user!", e);
      result = "/loginError?faces-redirect=true";
    }
    
    return result;
  }
} 
 
Como pueden ver en el Servlet 3.0 se ha agregado el m茅todo logout que hace que el contenedor se "olvide" de las credenciales de usuario.

Nota: Para el caso de las contrase帽as se coloc贸 un string hasheado mediante el algoritmo MD5, cuando se configure el Realm se debe especificar que algoritmo se utiliza para las contrase帽as (MD5, SHA256,etc)

Eso fue todo por este d铆a, espero que les sea de suma utilidad este tutorial para cuando tengan que desarrollar alguna aplicaci贸n con Java EE.

Saludos y hasta la pr贸xima! :)

mi茅rcoles, 5 de septiembre de 2012

INSTALACI脫N DEL SGBD ORACLE 11G


INSTALACI脫N DEL SGBD ORACLE 11G (RHEL/CentOS/Fedora)


Este es un peque帽o manual destinado a todos aquellos que quieran realizar una instalaci贸n del motor de bases de datos de Oracle en una distribuci贸n de GNU/Linux
Requerimientos del sistema:
  1. La cantidad m铆nima de RAM que se necesita es de 1Gb. La cantidad recomendada es cualquier configuraci贸n que tenga m谩s de 1Gb.
  2. Espacio m铆nimo libre en disco para la instalaci贸n 3.95Gb m谩s el espacio libre para datos de 1.7Gb, y la recomendada es de una configuraci贸n mayor a la m铆nima.
  3. Cualquier sistema operativo es soportado para la configuraci贸n m铆nima.

Descripci贸n general:  

Oracle es un manejador de base de datos relacional que hace uso de los recursos del sistema inform谩tico en todas las arquitecturas de hardware, para garantizar su aprovechamiento al m谩ximo en ambientes cargados de informaci贸n. Oracle corre en computadoras personales (PC), microcomputadoras, mainframes y computadoras con procesamiento paralelo masivo. Corre autom谩ticamente en m谩s de 80 arquitecturas de hardware y software distinto sin tener la necesidad de cambiar una sola l铆nea de c贸digo. Esto es porque m谩s el 80% de los c贸digos internos de Oracle son iguales a los establecidos en todas las plataformas de sistemas operativos. 
Oracle tambi茅n da soporte para dispositivos en bruto (Raw devices), tiene la ventaja de que la ejecuci贸n es un 50% m谩s r谩pido que sobre un dispositivo con un sistema de archivos. Las desventajas son que: El respaldo de una base de datos que utiliza un dispositivo en bruto no es tan simple y no es soportado por todos los proveedores de BackUp; Los nombres de archivos est谩n limitados a una sintaxis espec铆fica y solo se permite un archivo por partici贸n del dispositivo. Adem谩s, en la mayor铆a de los casos que existen problemas de rendimiento se debe a indices mal puestos o a extensiones excesivas de tabla, etc.
Bueno, basta de ch谩chara, vamos manos a la obra:

Instalaci贸n (Pasos previos): 
Antes de poder comenzar con la instalaci贸n es necesario realizar varias tareas, como instalar dependencias y configurar determinados par谩metros del kernel y agregar y configurar los usuarios del SO que utiliza el motor.
Primero nos aseguramos de que tengamos instaladas todas las dependencias en el sistema. La lista de las dependencias necesarias es la siguiente (No existe una lista para CentOS o Fedora, pero como ambas est谩n basadas o soportadas por RedHat vamos a tomar las dependencias de 茅sta):

binutils-2.17.50.0.6
compat-libstdc++-33-3.2.3
elfutils-libelf-0.125
elfutils-libelf-devel-0.125
elfutils-libelf-devel-static-0.125
gcc-4.1.2
gcc-c++-4.1.2
glibc-2.5-24
glibc-common-2.5
glibc-devel-2.5
glibc-headers-2.5
kernel-headers-2.6.18
ksh-20060214
libaio-0.3.106
libaio-devel-0.3.106
libgcc-4.1.2
libgomp-4.1.2
libstdc++-4.1.2
libstdc++-devel-4.1.2
make-3.81
sysstat-7.0.2
unixODBC-2.2.11
unixODBC-devel-2.2.11

Para verificar las dependencias ejecutamos el comando siguiente como superusuario:

# rpm -q binutils compat-libstdc++ elfutils-libelf elfutils-libelf-devel elfutils-libelf-devel-static gcc gcc-c++ glibc glibc-common glibc-devel glibc-headers kernel-headers ksh libaio-devel libaio libgcc libgomp libstdc++ libstdc++-devel make sysstat unixODBC unixODBC-devel

binutils-2.21.51.0.6-6.fc15.i686
package compat-libstdc++ is not installed
elfutils-libelf-0.152-1.fc15.i686
package elfutils-libelf-devel is not installed
package elfutils-libelf-devel-static is not installed
package gcc is not installed
package gcc-c++ is not installed
glibc-2.14-5.i686
glibc-common-2.14-5.i686
package glibc-devel is not installed
package glibc-headers is not installed
package kernel-headers is not installed
package ksh is not installed
package libaio-devel is not installed
libaio-0.3.109-3.fc15.i686
libgcc-4.6.0-10.fc15.i686
package libgomp is not installed
libstdc++-4.6.0-10.fc15.i686
package libstdc++-devel is not installed
make-3.82-4.fc15.i686
package sysstat is not installed
package unixODBC is not installed
package unixODBC-devel is not installed

La salida del comando nos indica, en el caso de que tengamos instaladas las dependencias, su versi贸n, y en caso contrario nos indica que no se encuentran instaladas. Procedemos a instalarlas ejecutando el siguiente comando:

# yum install compat-libstdc++ elfutils-libelf-devel elfutils-libelf-devel-static gcc gcc-c++ glibc-devel glibc-headers kernel-headers pdksh libaio-devel libgomp libstdc++-devel sysstat unixODBC unixODBC-devel

Loaded plugins: langpacks, presto, refresh-packagekit
Setting up Install Process
No package compat-libstdc++ available.
Resolving Dependencies
--> Running transaction check
---> Package elfutils-libelf-devel.i686 0:0.152-1.fc15 will be installed
---> Package elfutils-libelf-devel-static.i686 0:0.152-1.fc15 will be installed
---> Package gcc.i686 0:4.6.0-10.fc15 will be installed
--> Processing Dependency: cpp = 4.6.0-10.fc15 for package: gcc-4.6.0-10.fc15.i686
--> Processing Dependency: cloog-ppl >= 0.15 for package: gcc-4.6.0-10.fc15.i686
--> Processing Dependency: libmpc.so.2 for package: gcc-4.6.0-10.fc15.i686
---> Package gcc-c++.i686 0:4.6.0-10.fc15 will be installed
---> Package glibc-devel.i686 0:2.14-5 will be installed
---> Package glibc-headers.i686 0:2.14-5 will be installed
---> Package kernel-headers.i686 0:2.6.40.3-0.fc15 will be installed
---> Package ksh.i686 0:20110505-2.fc15 will be installed
---> Package libaio-devel.i686 0:0.3.109-3.fc15 will be installed
---> Package libgomp.i686 0:4.6.0-10.fc15 will be installed
---> Package libstdc++-devel.i686 0:4.6.0-10.fc15 will be installed
---> Package sysstat.i686 0:9.0.6.1-14.fc15 will be installed
---> Package unixODBC.i686 0:2.2.14-13.fc15 will be installed
---> Package unixODBC-devel.i686 0:2.2.14-13.fc15 will be installed
--> Running transaction check
---> Package cloog-ppl.i686 0:0.15.9-3.fc15 will be installed
--> Processing Dependency: libppl.so.9 for package: cloog-ppl-0.15.9-3.fc15.i686
--> Processing Dependency: libppl_c.so.4 for package: cloog-ppl-0.15.9-3.fc15.i686
---> Package cpp.i686 0:4.6.0-10.fc15 will be installed
---> Package libmpc.i686 0:0.8.3-0.3.svn855.fc15 will be installed
--> Running transaction check
---> Package ppl.i686 0:0.11.2-1.fc15 will be installed
--> Processing Dependency: libpwl.so.5 for package: ppl-0.11.2-1.fc15.i686
--> Running transaction check
---> Package ppl-pwl.i686 0:0.11.2-1.fc15 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

===============================================================================
Package Arch Version Repository
Size
===============================================================================
Installing:
elfutils-libelf-devel i686 0.152-1.fc15 fedora 31 k
elfutils-libelf-devel-static i686 0.152-1.fc15 fedora 66 k
gcc i686 4.6.0-10.fc15 updates 11 M
gcc-c++ i686 4.6.0-10.fc15 updates 4.9 M
glibc-devel i686 2.14-5 updates 977 k
glibc-headers i686 2.14-5 updates 605 k
kernel-headers i686 2.6.40.3-0.fc15 updates 753 k
ksh i686 20110505-2.fc15 updates 756 k
libaio-devel i686 0.3.109-3.fc15 fedora 12 k
libgomp i686 4.6.0-10.fc15 updates 90 k
libstdc++-devel i686 4.6.0-10.fc15 updates 1.3 M
sysstat i686 9.0.6.1-14.fc15 fedora 212 k
unixODBC i686 2.2.14-13.fc15 fedora 377 k
unixODBC-devel i686 2.2.14-13.fc15 fedora 52 k
Installing for dependencies:
cloog-ppl i686 0.15.9-3.fc15 fedora 93 k
cpp i686 4.6.0-10.fc15 updates 3.9 M
libmpc i686 0.8.3-0.3.svn855.fc15 fedora 49 k
ppl i686 0.11.2-1.fc15 fedora 1.5 M
ppl-pwl i686 0.11.2-1.fc15 fedora 35 k

Transaction Summary
===============================================================================
Install 19 Package(s)

Total size: 27 M
Total download size: 23 M
Installed size: 71 M
Is this ok [y/N]: y
Downloading Packages:
Setting up and reading Presto delta metadata
Processing delta metadata
Package(s) data still to download: 23 M
(1/17): elfutils-libelf-devel-0.152-1.fc15.i686.rpm | 31 kB 00:01
(2/17): elfutils-libelf-devel-static-0.152-1.fc15.i686. | 66 kB 00:00
(3/17): gcc-4.6.0-10.fc15.i686.rpm | 11 MB 02:54
(4/17): gcc-c++-4.6.0-10.fc15.i686.rpm | 4.9 MB 01:28
(5/17): glibc-devel-2.14-5.i686.rpm | 977 kB 00:35
(6/17): glibc-headers-2.14-5.i686.rpm | 605 kB 00:19
(7/17): kernel-headers-2.6.40.3-0.fc15.i686.rpm | 753 kB 00:29
(8/17): ksh-20110505-2.fc15.i686.rpm | 756 kB 00:12
(9/17): libaio-devel-0.3.109-3.fc15.i686.rpm | 12 kB 00:01
(10/17): libgomp-4.6.0-10.fc15.i686.rpm | 90 kB 00:02
(11/17): libmpc-0.8.3-0.3.svn855.fc15.i686.rpm | 49 kB 00:01
(12/17): libstdc++-devel-4.6.0-10.fc15.i686.rpm | 1.3 MB 00:19
(13/17): ppl-0.11.2-1.fc15.i686.rpm | 1.5 MB 00:16
(14/17): ppl-pwl-0.11.2-1.fc15.i686.rpm | 35 kB 00:00
(15/17): sysstat-9.0.6.1-14.fc15.i686.rpm | 212 kB 00:02
(16/17): unixODBC-2.2.14-13.fc15.i686.rpm | 377 kB 00:08
(17/17): unixODBC-devel-2.2.14-13.fc15.i686.rpm | 52 kB 00:00
-------------------------------------------------------------------------------
Total 55 kB/s | 23 MB 07:07
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
Installing : elfutils-libelf-devel-0.152-1.fc15.i686 1/19
Installing : libstdc++-devel-4.6.0-10.fc15.i686 2/19
Installing : kernel-headers-2.6.40.3-0.fc15.i686 3/19
Installing : libmpc-0.8.3-0.3.svn855.fc15.i686 4/19
Installing : glibc-headers-2.14-5.i686 5/19
Installing : glibc-devel-2.14-5.i686 6/19
Installing : cpp-4.6.0-10.fc15.i686 7/19
Installing : ppl-pwl-0.11.2-1.fc15.i686 8/19
Installing : ppl-0.11.2-1.fc15.i686 9/19
Installing : cloog-ppl-0.15.9-3.fc15.i686 10/19
Installing : libgomp-4.6.0-10.fc15.i686 11/19
Installing : gcc-4.6.0-10.fc15.i686 12/19
Installing : unixODBC-2.2.14-13.fc15.i686 13/19
Installing : unixODBC-devel-2.2.14-13.fc15.i686 14/19
Installing : elfutils-libelf-devel-static-0.152-1.fc15.i686 15/19
Installing : libaio-devel-0.3.109-3.fc15.i686 16/19
Installing : gcc-c++-4.6.0-10.fc15.i686 17/19
Installing : sysstat-9.0.6.1-14.fc15.i686 18/19
Installing : ksh-20110505-2.fc15.i686 19/19

Installed:
elfutils-libelf-devel.i686 0:0.152-1.fc15
elfutils-libelf-devel-static.i686 0:0.152-1.fc15
gcc.i686 0:4.6.0-10.fc15
gcc-c++.i686 0:4.6.0-10.fc15
glibc-devel.i686 0:2.14-5
glibc-headers.i686 0:2.14-5
kernel-headers.i686 0:2.6.40.3-0.fc15
ksh.i686 0:20110505-2.fc15
libaio-devel.i686 0:0.3.109-3.fc15
libgomp.i686 0:4.6.0-10.fc15
libstdc++-devel.i686 0:4.6.0-10.fc15
sysstat.i686 0:9.0.6.1-14.fc15
unixODBC.i686 0:2.2.14-13.fc15
unixODBC-devel.i686 0:2.2.14-13.fc15

Dependency Installed:
cloog-ppl.i686 0:0.15.9-3.fc15 cpp.i686 0:4.6.0-10.fc15
libmpc.i686 0:0.8.3-0.3.svn855.fc15 ppl.i686 0:0.11.2-1.fc15
ppl-pwl.i686 0:0.11.2-1.fc15

Complete!





Ahora todos las dependencias ya est谩n instaladas a excepci贸n de compat-libstdc++, que vamos a instalar m谩s adelante porque no est谩 en los repositorios de la actual distribuci贸n.

Ahora toca configurar los grupos y usuarios para Oracle. Ellos son:

  • El grupo de inventario (t铆picamente, oinstall)
  • El grupo OSDBA (t铆picamente, dba)
  • El due帽o del software (t铆picamente, oracle)
  • El grupo OSOPER (opcional. T铆picamente, oper)

Para agregar los grupo ejecutamos los siguientes comandos:

# groupadd oinstall
# groupadd dba


Y luego para crear el usuario y agregarlo al grupo correspondiente:

# useradd -g oinstall -G dba oracle

Pedir谩 la contrase帽a para el usuario e ingresamos “oracle” (o cualquier otra) y listo. Si ejecutamos el siguiente comando:

# id oracle

La salida debe ser algo parecido a esto:

uid=501(oracle) gid=503(oinstall) groups=503(oinstall),501(dba)



El paso siguiente es ver si determinados par谩metros del n煤cleo est谩n correctos. En la gu铆a de instalaci贸n de Oracle especifica cuales son y sus valores:

Par谩metro
Valor m铆nimo
Archivo
semmsl
semmns
semopm
semmn
250
3200
100
128
/proc/sys/kernel/sem
shmall
2097152
/proc/sys/kernel/shmall
shmmax
Puede ser 4 GB - 1 byte, o la mitad del tama帽o de la memoria f铆sica (en bytes), el que sea menor.
Defecto: 536870912
/proc/sys/kernel/shmmax
shmmni
4096
/proc/sys/kernel/shmmni
file-max
512 * PROCESSES
/proc/sys/fs/file-max
ip_local_port_range
Min: 9000 Max: 65500
/proc/sys/net/ipv4/ip_local_port_range
rmem_default
262144
/proc/sys/net/core/rmem_default
rmem_max
4194304
/proc/sys/net/core/rmem_max
wmem_default
262144
/proc/sys/net/core/wmem_default
wmem_max
1048576
/proc/sys/net/core/wmem_max
aio-max-nr
M谩ximo: 1048576
/proc/sys/fs/aio-max-nr




Para poder comprobar el estado de estos valores se pueden ejecutar los siguientes comandos:

Para: semmsl, semmns, semopm y semmn

# /sbin/sysctl -a | grep sem

Si se cambia el valor del par谩metro que sigue a “grep” por los par谩metros de la lista obtenemos el valor dichos par谩metros del n煤cleo.

# /sbin/sysctl -a | grep shmall
# /sbin/sysctl -a | grep shmmax
# /sbin/sysctl -a | grep shmmni
# /sbin/sysctl -a | grep file-max
# /sbin/sysctl -a | grep ip_local_port_range
# /sbin/sysctl -a | grep rmem_default
# /sbin/sysctl -a | grep rmem_max
# /sbin/sysctl -a | grep wmem_default
# /sbin/sysctl -a | grep wmem_max


Ahora lo que hacemos, si encontramos alg煤n par谩metro que no es el adecuado, es editar el archivo /etc/sysctl.conf mediante el comando nano o vi:

# nano /etc/sysctl.conf

E ingresamos los siguientes valores solo si los par谩metros actuales tienen un valor menor.

fs.aio-max-nr = 1048576
fs.file-max = 6815744
kernel.shmall = 2097152
kernel.shmmax = 536870912
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
net.ipv4.ip_local_port_range = 9000 65500
net.core.rmem_default = 262144
net.core.rmem_max = 4194304
net.core.wmem_default = 262144
net.core.wmem_max = 1048586

Guardamos los cambios en el archivo y reiniciamos la computadora.


Ahora vamos a darle “superpoderes” al usuario oracle editando el archivo /etc/security/limits.conf mediante el comando nano o vi:

# nano /etc/security/limits.conf

Y a帽adimos las siguientes l铆neas al final del archivo:

oracle soft nproc 2047
oracle hard nproc 16384
oracle soft nofile 1024
oracle hard nofile 65536

Guardamos los cambios y listo.

Ahora editamos el archivo /etc/pam.d/login:

# nano /etc/pam.d/login

Y a帽adimos al final (si es que ya no est谩) la siguiente l铆nea:

session required pam_limits.so

Guardamos y listo.

Ahora falta configurar el ambiente para el usuario oracle. Para ello nos logueamos en un terminal con el usuario oracle y ejecutamos el siguiente comando:

$ nano .bash_profile

Y colocamos debajo de la secci贸n “User specific environment and startup programs” lo siguiente:

umask 022

Ya tenemos configurado los usuarios, los grupos, los par谩metros del kernel y algunas opciones para mejorar el rendimiento.


Ahora nos logueamos al sistema con el usuario oracle que creamos, ingresamos a la web de Oracle y descargamos los instaladores, luego descomprimimos los archivos de instalaci贸n (parte 1 y parte 2) y nos movemos al directorio donde los descomprimimos con el siguiente comando:

$ cd database/
$ ./runInstaller

Starting Oracle Universal Installer...

Checking Temp space: must be greater than 80 MB. Actual 16043 MB Passed
Checking swap space: must be greater than 150 MB. Actual 2111 MB Passed
Checking monitor: must be configured to display at least 256 colors. Actual 16777216 Passed
Preparing to launch Oracle Universal Installer from /tmp/OraInstall2011-09-06_12-46-45AM. Please wait ...


Finalmente se muestra la primer pantalla del asistente de instalaci贸n.



Aqu铆 nos pide nuestra direcci贸n de email y nuestra contrase帽a de usuario de la web de oracle para recibir notificaciones sobre actualizaciones de seguridad y soporte. Quitamos la selecci贸n de esa casilla e ingresamos nuestro email y hacemos clic en “Next”. La siguiente pantalla aparece:



En esta pantalla seleccionamos la primer opci贸n puesto que luego de instalar el motor de base de datos vamos a crear una base de datos. La segunda opci贸n instala solo el motor pero no nos gu铆a para crear una base de datos. La tercer opci贸n es para actualizar una instalaci贸n preexistente. Presionamos “Next”.



Aqu铆 nos solicita el tipo de computadora donde queremos instalar y nos presenta dos opciones posibles “Desktop class” que es para instalar el motor con las opciones por defecto para un ordenador de escritorio o notebook y tener el servicio corriendo lo m谩s r谩pido posible. La otra opci贸n “Server class” es para instalar el motor en un servidor de producci贸n y con opciones avanzadas. Para los prop贸sitos de 茅ste trabajo seleccionamos “Server class” y damos a “Next”.




En esta pantalla nos pregunta acerca de la configuraci贸n para “Grid” que es un conjunto de bases de datos colaborando entre si. Las dos opciones posibles son “Single instance database instalaltion” y “Real Application Clusters database installation”. En la primera tenemos una 煤nica instancia en nuestra computadora y con la otra podremos configurar una red de bases de datos. Seleccionamos la primer opci贸n y hacemos clic en “Next”.




En esta pantalla nos solicita el tipo de instalaci贸n “Typical install” y “Advanced install”. Seleccionamos la segunda opci贸n para disponer de las opciones de instalaci贸n avanzada y presionamos “Next”.




Ahora nos pide el idioma de instalaci贸n para el motor. Seleccionamos “Spanish” en la lista de la izquierda y hacemos clic en la flecha hacia la derecha para agregarla a la lista de la derecha. El idioma ingl茅s no puede ser removido de la lista de la derecha. Presionamos “Next”



En la pantalla actual nos solicita el tipo de edici贸n que queremos instalar. Seleccionamos “Enterprise edition” y si hacemos clic en “Select options” podremos agregar o quitar algunos componentes adicionales. Dejamos seleccionados los que est谩n por defecto que son: “Oracle partitioning”, “Oracle OLAP”, “Oracle Data Mining RDBMS Files” y “Oracle Real Applications Testing”. Presionamos “Ok” y luego “Next”.



En esta pantalla nos pregunta primero el directorio de base y segundo el directorio donde se van a instalar todos los programas que componen al motor. Dejamos los que est谩n por defecto y presionamos “Next”.



Ahora nos solicita que ingresemos la ruta del directorio de inventario que es donde Oracle instala los componentes adicionales para que las diferentes instalaciones de Oracle lo compartan. Adem谩s nos pide el grupo de usuarios que tienen permiso sobre ese directorio. Dejamos las opciones por defecto y presionamos “Next”.



En la pantalla actual nos pregunta acerca del tipo de base de datos que deseamos configurar. Tenemos dos opciones. La primera “General purpose / Transaction processing” que es para una base de datos de prop贸sito general y para el soporte de transacciones pesadas. La segunda “Data warehousing” que es para el almacenamiento masivo de datos a lo largo del tiempo para su posterior uso en la toma de decisiones, como por ejemplo patrones de compra de clientes, llamados a los mismos, etc y proporciona un acceso r谩pido a grandes vol煤menes de datos. Seleccionamos la primer opci贸n y damos a “Next”.



En esta pantalla nos solicita la identificaci贸n de nuestra instalaci贸n de Oracle. El identificador global y el identificador de servicio. Esto es para identificar una instalaci贸n puntual dentro de una red de bases de datos y el segundo campo indica el identificador local para que otras instancias de instalaci贸n hagan referencia a la actual instalaci贸n. Como es la 煤nica instancia que vamos a instalar dejamos las opciones por defecto.



En la pantalla actual nos da la opci贸n de que el motor gestione la memoria autom谩ticamente seg煤n el uso del mismo o nos deja a nuestro criterio la definici贸n del uso de memoria. La opci贸n por defecto es la gesti贸n autom谩tica. En la pesta帽a “Character sets” nos da la opci贸n de especificar un juego de caracteres para la base de datos. Dejamos la opci贸n por defecto que toma el juego de caracteres del S.O. En la pesta帽a de seguridad nos advierte que dejemos seleccionado el uso de las nuevas pol铆ticas de seguridad que es la opci贸n por defecto. Podemos desactivarla si lo consideramos necesario, pero en este caso dejamos seleccionado.



En la pesta帽a “sample schemas” podemos definir si instalar las bases de datos de ejemplo, seleccionamos la opci贸n y presionamos “Next”.



Ahora nos pregunta si deseamos gestionar la instalaci贸n mediante un control para GRID preexistente o si deseamos gestionar la instancia con el gestor de Oracle y recibir notificaciones por mail. Dejamos seleccionada la opci贸n por defecto que es “Use database control for database management”, es decir, gestionar la instancia con el administrador local. Sacamos la selecci贸n de env铆o de notificaciones puesto que solicita la configuraci贸n de un servidor SMTP y eso es otra historia. Presionamos “Next” para continuar.



En la pantalla actual debemos indicar si vamos a utilizar el sistema de archivos del SO para el almacenamiento de la base de datos y nos suguiere que si as铆 lo hacemos coloquemos la ruta de un disco diferente. Tambi茅n permite la opci贸n del servicio automatizado de almacenamiento, el cual determina por si solo las mejores ubicaciones para los archivos. Dejamos la opci贸n por defecto que es utilizar el sistema de archivos y presionamos “Next”.



En esta pantalla nos pregunta acerca de los resguardos autom谩ticos, si los habilitamos o no, y en el caso de seleccionar la primer opci贸n debemos indicar el tipo de almacenamiento que queramos para los resguardos (sistema de archivos o autom谩tico, como en la pantalla anterior). Dejamos la opci贸n por defecto que es no hacer resguardos autom谩ticos y presionamos “Next”.



En la pantalla actual nos solicita que ingresemos una contrase帽a diferente para cada uno de los usuarios de administraci贸n para el motor o bien que establezcamos la misma para todos. Por razones de comodidad (y para evitar posibles olvidos y no tener que reinstalar todo de nuevo :P) vamos a seleccionar la misma contrase帽a para todos. Ingresamos la contrase帽a deseada. Si la contrase帽a no cumple con las recomendaciones de seguridad se mostrar谩 un mensaje. Presionamos “Next”.



Ahora nos solicita el grupo de usuarios a los que deben pertenecer los usuarios de administraci贸n del motor para adquirir los mismos permisos y as铆 poder gestionar la base de datos. Dejamos las opciones por defecto y presionamos “Next”.

El asistente procede a realizar una comprobaci贸n del sistema:

El asistente realiza un chequeo de los requisitos del sistema y luego nos informa de los problemas encontrados, si es que los hay:



En este caso se muestran problemas con algunos par谩metros del kernel que no son los adecuados, el tama帽o de la memoria est谩 por debajo del m铆nimo y existen problemas de dependencias de paquetes. Los problemas con los par谩metros del kernel pueden arreglarse. Presionamos “Fix & check again” y abrimos una consola, nos logueamos como root y ejecutamos el siguiente script generado por el asistente:

# /tmp/CVU_11.2.0.1.0_bda/runfixup.sh
Response file being used is :/tmp/CVU_11.2.0.1.0_bda/fixup.response
Enable file being used is :/tmp/CVU_11.2.0.1.0_bda/fixup.enable
Log file location: /tmp/CVU_11.2.0.1.0_bda/orarun.log
uid=502(bda) gid=502(bda) groups=502(bda)
Ahora bien, estos errores pueden ignorarse y continuar con la instalaci贸n, pero lo m谩s probable es que empiecen a aparecer errores y la instalaci贸n falle. Es por eso que si encontramos problemas de memoria y de espacio de intercambio es mejor volver a instalar nuestro S.O o tratar de modificar esos aspectos si es posible.
Los problemas de dependencias de paquetes se solucionan f谩cilmente. Visitamos la p谩gina rpmfind.net y buscamos por los paquetes que faltan, los descargamos y los instalamos mediante el siguiente comando:

# rpm -i <paquete1.rpm> ... <paqueteN.rpm>

El en caso del paquete pdksh, que es un int茅rprete de comandos que ninguno de los usuarios configurados utiliza y en Fedora se llama ksh (Korn Shell), no se puede instalar porque entra con conflicto con otro int茅rprete que se llama bash, que es el utilizado de manera predefinida. Esta dependencia puede ser ignorada sin ning煤n problema.




Finalmente nos muestra un 谩rbol de resumen con la posibilidad de guardar el archivo de respuestas para una futura instalaci贸n. Presionamos “Finish” para que comience la instalaci贸n.


El asistente muestra las tareas que se est谩n realizando y el progreso de las mismas.





En el caso de esta instalaci贸n ocurri贸 un error debido a que la versi贸n instalada del compilador de C es m谩s reciente que la requerida por la instalaci贸n, de modo que tuvimos que solucionarlo editando un archivo de instalaci贸n:

Guardamos el archivo y presionamos “Retry” en el asistente para que vuelva a intentar realizar la acci贸n err贸nea.


Al final de la instalaci贸n nos pide que ejecutemos uno o m谩s scripts como superusuario:


# /home/bda/app/oraInventory/orainstRoot.sh

Changing permissions of /home/bda/app/oraInventory.
Adding read,write permissions for group.
Removing read,write,execute permissions for world.

Changing groupname of /home/bda/app/oraInventory to bda.
The execution of the script is complete.

# /home/bda/app/bda/product/11.2.0/dbhome_1/root.sh
Running Oracle 11g root.sh script...

The following environment variables are set as:
ORACLE_OWNER= bda
ORACLE_HOME= /home/bda/app/bda/product/11.2.0/dbhome_1

Enter the full pathname of the local bin directory: [/usr/local/bin]:
Copying dbhome to /usr/local/bin ...
Copying oraenv to /usr/local/bin ...
Copying coraenv to /usr/local/bin ...


Creating /etc/oratab file...
Entries will be added to the /etc/oratab file as needed by
Database Configuration Assistant when a database is created
Finished running generic part of root.sh script.
Now product-specific root actions will be performed.
Finished product-specific root actions.


Al finalizar la instalaci贸n el asistente nos indica que se ha llevado a cabo con 茅xito.
Una vez que el asistente ah finalizado, se inicia el servicio de bases de datos y el servicio de la consola de administraci贸n en un contenedor web local. Para acceder al mismo nos proporciona una direcci贸n, la cual accedemos mediante un navegador web:


Al acceder a esta direcci贸n se nos presenta la siguiente p谩gina web:


Aqu铆 nos solicita que ingresemos un nombre de usuario y contrase帽a. 脡stos datos son los que nos solicit贸 durante la instalaci贸n. Ingresamos mediante el usuario “SYSTEM” y la contrase帽a que configuramos en la instalaci贸n.

La siguiente pantalla nos muestra un resumen muy completo del estado actual de los componentes del RDBMS, como por ejemplo el uso del procesador, el tiempo de respuesta para las consultas, el estado de la escucha de red, como as铆 tambi茅n algunas advertencias sobre recomendaciones de seguridad y rendimiento. Tambi茅n nos informa sobre el tama帽o de la base de datos, algunos problemas que pueda tener y el espacio disponible. Podemos ver el estado general del motor de un vistaso.




Haciendo clic en “Esquema” nos muestra una pantalla en la que podremos modificar los objetos del esquema de la base de datos, como las tablas, las vistas, las secuencias, los 铆ndices, las vistas, etc. Luego en la pesta帽a de “Movimiento de datos” encontramos las opciones para exportar e importar datos a la base de datos.
Y as铆 ya tenemos instalado nuestro motor de bases de datos! :)

Hasta la pr贸xima!!