lunes, 8 de febrero de 2016

Angular 2, esqueleto de la aplicación

En el articulo anterior vimos, como crear un hola mundo, en este articulo vamos a ver como hacer el esqueleto de nuestra aplicación, vamos a dividir la pantalla en los siguientes apartados:

  • Cabecera: Sera donde se encontrara la cabecera de nuestra aplicación.
  • Cuerpo: Es donde vamos a establecer las pantallas, de nuestra aplicación.
  • Pie: Es donde pondremos la información de nuestra aplicación.
En el siguiente enlace  se puede encontrar este articulo.

Crear una plantilla par el componente de aplicación

Ahora los que vamos a ver es como separar el controlador de la vista, para lo cual simplemente en la configuración del decorador del componente, cambiaremos el atributo de template, por el de templateUrl en el que le vamos a indicar donde se va a encontrar el archivo donde se va a encontrar el fichero con la nueva plantilla ('/app/app.component.html'). A partir de ahora sera la forma de indicar donde se encuentra la plantilla que representa la región de vista que controlara nuestro controlador.

app.component.html
<p>Nueva pagina de hola mundo.</p>
Cambiamos el testo que tiene la plantilla y creamos el nuevo fichero de la vista para que nos salude.

 app.component.ts
import {Component} from 'angular2/core';
@Component({
  selector:'my-app',
  templateUrl:'/app/app.component.html'
})
export class AppComponent{};

Ahora que por un lado hemos visto como se puede separar en angular la vista y el controlador en dos ficheros independientes, vamos a crear un componente nuevo por las 3 nuevas regiones que vamos a establecer.

La norma que voy a seguir, es la de llamar igual a la vista y el controlador. Para que sea fácil buscarlo.

Creamos el componente de la cabecera:

Ahora vamos a crear el componente cabecera, que tendrá el selector dbpCabecera .

/app/component/comun/cabecera.component.html

<p> Aqui ira la cabecera </p>

/app/component/comun/cabecera.component.ts


import {Component} from 'angular2/core';
@Component({
  selector:'dpbCabecera',
  templateUrl:'/app/component/comun/cabecera.component.html'
})
export class CabeceraComponent{}


Creamos el componente del cuerpo:

Ahora vamos a crear el component cuerpo, que tendrá el selector dbpCuerpo.

/app/component/comun/cuerpo.component.html

<p> Aqui ira el código del cuerpo </p>
/app/component/comun/cuerpo.component.ts


import {Component} from 'angular2/core';

@Component({
  selector:'dbpCuerpo',
  templateUrl:'/app/component/comun/cuerpo.component.html'
})
export class CupoerComponent{}


Creamos el componente del pie

Ahora vamos a crear el componente del pie, que tendrá el selector dbpPie

/app/component/comun/pie.component.html
<p>Aqui ira el código del pie</p>
/app/component/comun/pie.component.ts

import {Component} from 'angular2/core';
@Component({
  selector:'dpbPie',
  templateUrl:'/app/component/comun/pie.component.html'
})
export class PieComponent{}

Ahora que ya tenemos creados los 3 componentes que van a representar las regiones de pantalla que hemos detallado al principio del articulo, tenemos que ver como vamos a vincular a nuestro componente principal, estos tres componentes.

Asociamos a los componentes nuevos a la aplicación.

Antes de nada aquí vamos a ver un primer ejemplo que angular 2 la forma que tiene de construir la pantalla, es con un árbol de componente que se irán asociando y se puede comunicar entre ellos. Para lo cual tenemos que realizar 2 cosas:

  • Asociar el componente al controlador.
  • Indicar en la plantilla del componente padre donde vamos a pintar cada uno de los componentes.

Asociar al controlador:

En este caso lo que vamos hace es indicarle al componente donde se encuentran sus hijos para lo cual por un lado lo tenemos que importar por un lado el componente y por otro lado pasárselos al componente con el parámetro directives.


import {Component} from 'angular2/core';
import {CabeceraComponent} from './component/comun/cabecera.component';
import {CuerpoComponent} from './component/comun/cuerpo.component';
import {PieComponent} from './component/comun/pie.component';
@Component({
  selector:'my-app',
  templateUrl:'/app/app.component.html',
  directives:[CabeceraComponent,CuerpoComponent,PieComponent]
})
export class AppComponent{};

Indicarlo en la plantilla donde ira cada componente

Ahora solo tenemos que indicar, donde vamos a pintar cada uno de los elementos en la pantalla de la aplicación.
<dpbCabecera></dpbCabecera>
<dbpCuerpo></dbpCuerpo>
<dpbPie></dpbPie>

Conclusión

Como podemos ver en este articulo, por un lado que separa la vista del controlador, como se monta un árbol de componente básicos y como se pueden asociar.


lunes, 18 de enero de 2016

Como empezar con "Angular 2" (BETA)

Acaba de salir hace poco la beta de angular 2, y vamos a ver como crear la estructura básica de un proyecto , para lo cual el articulo lo vamos a dividir en 3 partes:
  • Que es angular 2.
  • Configurar nuestro entorno de desarrollo. 
  • Estructura básica de un proyecto de angular 2.
Ojo, hay que tener en cuenta que este articulo se ha realizado con la beta.0 y pueden cambiar algunas cosas. 
En la siguiente url  os podéis descargar el proyecto  de este articulo 

¿Que nos ofrece angular 2?

Antes de utilizar un framework tenemos que saber que nos ofrece y si nos merece la pena.
  • Esta pensado para poder hacer aplicaciones mobiles y proporcionarnos mecanismos, que nos permitan realizar las performance. 
  • Es mas rápido, ya que las actualizaciones se hacen sobre los datos y no en el árbol DOM.
  • Flexible:
    • Múltiples lenguajes:
      • javascript
      • typescript (Este es el que recomiendan y vamos a usar nosotros).
      • dart
    • Mezcla por una lado el estilo de objetos (Clases y decorators (anotaciones de java)), mas la programación funcional y reactiva (para los flujos de datos).
Esto es lo que nos dice la gente de angular 2, yo al menos el ultimo punto por lo que he visto les ha quedado bastante bien, al menos para la gente que venimos del mundo de spring. De las aplicaciones mobiles tampoco piloto tanto para juzgarlo, pero por lo poco que he leído si lo están teniendo en cuanto al menos en el ancho de banda y otras historias. 

Herramientas que vamos a usar:

 Se necesitan las siguientes herramientas, para poder trabajar:
  • nodejs: Para descargar las herramientas necesarias.
  • atomjs: Usaremos el editor de texto atom, que se integra con github + el pluging de typescript
  • pluging de typescript: Instalamos en atom el siguiente pluging https://atom.io/packages/atom-typescript.
Estas herramientas, solo las vamos a tener que instalar.

Dependencias que vamos a necesitar:

Ahora que tenemos las herramientas, vamos a ver las dependencias que vamos a necesitar para poder trabajar a angular 2:
  • angular2: la versión (2.0.0-beta.0).
  • systemjs: la versión (0.19.6).
  • es6-promise: la versión (3.0.2).
  • es6-shim: la versión (0.33.3).
  • reflect-metadata: la versión (0.1.2).
  • rxjs: la versión (5.0.0-beta.0).
  • zone.js: la versión (0.5.10).
Las dependencias de desarrollo
  • concurrently: la versión (1.0.0)
  • lite-server: la versión (1.3.1)
  • typescript: la versión (1.7.3)
Para poder configurar todas estas dependencias vamos a utilizar el fichero de package.json

{
  "name": "angular2-holamund",
  "version": "1.0.0",
  "license": "ISC",
  "dependencies": {
    "angular2": "2.0.0-beta.0",
    "systemjs": "0.19.6",
    "es6-promise": "^3.0.2",
    "es6-shim": "^0.33.3",
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-beta.0",
    "zone.js": "0.5.10"
  },
  "devDependencies": {
    "concurrently": "^1.0.0",
    "lite-server": "^1.3.1",
    "typescript": "^1.7.3"
  }
}

Una vez que hemos creado el fichero de package.json, lo siguiente que tenemos que hacer es ponerlos en el directorio del proyecto y ejecutar el siguiente comando:
npm install
Una vez ejecutado este comando, se crear en la carpeta de node_modules, todas las dependencias que hemos puesto.

 Configurar el atom

Ahora vamos a ver como configurar en atom el typescript, para lo cual en la consola (ctrl + shift + p) de atom escribimos este comando "create tsconfig.json", ahora nos crea el fichero de tsconfig.json que le indica al compilador como tiene que trabajar typescript. Del fichero que nos genera yo le cambio el parámetro de buildOnSave a true, para que cada vez que se guarda un cambio se compilen los ficheros. Y para poder depurar establecemos el parámetro, "sourceMap".

{
    "compilerOptions": {
        "target": "es5",
        "module": "commonjs",
        "moduleResolution": "node",
         "sourceMap": true,
        "isolatedModules": false,
        "jsx": "react",
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "declaration": false,
        "noImplicitAny": false,
        "removeComments": true,
        "noLib": false,
        "preserveConstEnums": true,
        "suppressImplicitAnyIndexErrors": true
    },
    "filesGlob": [
        "**/*.ts",
        "**/*.tsx",
        "!node_modules/**"
    ],
    "compileOnSave": true,
    "buildOnSave": true,
    "files": [
        "boot.ts"
    ],
    "atom": {
        "rewriteTsconfig": true
    }
}
Ahora ya podemos trabajar con typescript en atom, 

Configurar el git

En nuestro ejemplo no vamos a guardar en el control de versiones:
  • *.js: Son los ficheros que se generar de los ts.
  • *.map: Son los map que generar de los ts, para la deuperación.
  • node_modules: Es un fichero de trabajo de node, que no tenemos que subir el control de versiones.
Fichero: .gitignore
*.js
*.map
node_modules

Ahora en el directorio raíz creamos este fichero, y ademas estos ficheros ya no se verán en el atom.

Configurar el nodejs

Ahora que ya tenemos configuradas las dependencias, el editor de texto y el control de versiones. Solo nos falta montar en el nodejs, un compilador de typscript y un servidor ligero para poder trabajar. Para lo cual ampliaremos el fichero package.json, ahora vamos a definir el modulo de scripts:
  • Lanzar el servidor ("start": "live-server"). npm start
Así quedaría el fichero package.json

{
  "name": "angular2-holamund",
  "version": "1.0.0",
  "license": "ISC",
  "scripts": {
    "tsc": "tsc -p app -w",
    "start": "live-server"
  },
  "dependencies": {
    "angular2": "2.0.0-beta.0",
    "systemjs": "0.19.6",
    "es6-promise": "^3.0.2",
    "es6-shim": "^0.33.3",
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-beta.0",
    "zone.js": "0.5.10"
  },
  "devDependencies": {
    "concurrently": "^1.0.0",
    "lite-server": "^1.3.1",
    "typescript": "^1.7.3"
  }
}

Ya tenemos configurado nuestro entorno para empezar a trabajar con angular 2, cuento todos estos pasos por que al menos para mi la primera vez me llevo algo de tiempo montar toda la infraestructura de primeras.

Estructura de nuestro proyecto

En este apartado vamos a ver los ficheros que vamos a necesitar para montar nuestro ejemplo.

A continuación vamos a ver los ficheros que tenemos que crear.

/
/app
/app/app.component.ts
/app/boot.ts
/index.html

Los fuentes los vamos a colocar en la carpeta app. Y el fichero donde va estar la pagina principal index.html lo ponemos en la basé del proyecto. 

Ahora vamos a ver el orden en el que vamos a seguir para escribir nuestra primera aplicación:
  1. Crear el componente de la aplicación (app.component.ts).
  2. Configurar el arranque de la aplicación (boot.ts).
  3. Escribir la pagina principal (index.html).  

Componente de aplicación (app.component.ts)

En este fichero vamos a crear el componente raiz, a partir del cual vamos a construir nuestra aplicación. 

En este fichero vamos a ver 3 cosas:
  • Como importar los recursos .  En nuestro caso sera el decorador @Component.
  • El atributo de componente selector, que sera un selector de la css, donde va a pintar angular 2 el componente.
  • El atributo de component template, que representa la región  de pantalla del controlador.
También tendremos la clase controlador, donde estará la lógica que gestiona el trozo de pantalla que podemos llamar vista. En nuestro ejemplo esta vacía ya que nuestra aplicación solo va a pintar hola mundo.

import {Component} from 'angular2/core';
@Component({
  selector: 'my-app',
  template:' Hola Mundo.'
})
export class AppComponent {}

Aquí es donde crearemos el esqueleto de nuestra aplicación de los componentes que siempre se verán en pantalla, como por ejemplo (El pie, el encabezado,cuerpo)...

Arranque de la aplicación (boot.ts)

Este fichero es el encargado de arrancar angular y establecer las configuraciones. En nuestro ejemplo solo le vamos a indicar cual va ser el componente raíz de la aplicación (AppComponent).


import {bootstrap}    from 'angular2/platform/browser'
import {AppComponent} from './app.component';

bootstrap(AppComponent);

Todos los servicios que se inyecten a este nivel los vera toda la aplicación y compartirán la misma instancia (vamos que sera un singlenton). Ojo en angular tambien podemos inyectar servicios en el contexto de los controladores...

Pagina principal (index.html)

Representa la pagina web, que sera la responsable de cargar nuestra aplicación. En la pagina vamos a tener 3 secciones diferenciadas.
  • Las librerías de javascript que vamos a utilizar. (es6-shim.js, angular2-polyfills, system.src.js, rx.js, angular2)
  • Configuración de systemjs (que es la herramienta encargada de cargar los módulos).
    • Por un lado le indicamos que vamos a registrar todos los ficheros que estan dentro de la carpeta app, con la extensión js.
    • Por otro lado le indicamos donde se encuentra el fichero por el que vamos a arrancar la aplicación.
  • Indicar la selección de la región de pantalla donde vamos a pintar la aplicación. Se cargar en la sección de pantalla de my-app.
...
<html>
  <head>
      <title> Angular 2 (Hola mundo)</title>

      <!-- 1. Cargamos las librerias -->
      <script src="node_modules/es6-shim/es6-shim.js"></script>
      <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
      <script src="node_modules/systemjs/dist/system.src.js"></script>
      <script src="node_modules/rxjs/bundles/Rx.js"></script>
      <script src="node_modules/angular2/bundles/angular2.dev.js"></script>

      <!-- 2. Configirar SystemJS -->
      <script>
        System.config({
          packages: {
                  'app': {defaultExtension: 'js' }
                }
          });
        System.import('app/boot')
              .then(null, console.error.bind(console));
      </script>
  </head>
  <body>
      <my-app> Cargando ...</my-app>
  </body
...

Ahora solo nos falta, arrancar la aplicación, con el comando npm start y ver como nos saluda la aplicación.

viernes, 27 de noviembre de 2015

Dao Generico + Spring + JPA 2

Aquí vamos,  a montar un dao genérico, que contenga las siguientes operaciones básicas:
  • ObtenerId: Nos obtiene la entidad asociada a un id.
  • Eliminar: Se encarga de eliminar la entidad que le pasamos.
  • Actualizar: Se encarga de actualizar la entidad que le pasamos.
  • Crear: Se encarga de crear un entidad.
  • Obtener todos:  Nos devuelve todos los registros del sistema.
La idea de un dao generico, es que estas operaciones las hereden todos los dao de nuestro proyecto, sin necesidad de tener que picarlas.
El dao genérico, se compone de una interfaz y una clase que implementa las operaciones.

En el siguiente proyecto podéis encontrar https://github.com/blancoparis-tfc/SpringCrud

Interfaz

Lo primer que tenemos que hacer es definir las operaciones, en una interfaz, en la cual además de las operaciones, vamos a definir en la cabecera de la interfaz, dos tipos genéricos, que van a representar a la entidad con la que vamos a trabajar y el id de la entidad.

Gracias a estos dos genéricos, es lo que va hacer la magia que nos va a permitir que estas operaciones valgan para cualquier de nuestras entidades del proyecto.

package org.dbp.core.dao;

import java.io.Serializable;
import java.util.List;

public interface GenericDao {

 public E obtenerId(ID id);

 public void eliminar(E entidad);
 
 public void crear(E entidad);
 
 public E actualizar(E entidad);
 
 public List obtenerTodos();
 
}

Clase

Ahora vamos a implementar las operaciones que hemos puesto en el interfaz, en la siguiente clase.

package org.dbp.core.dao.impl;

import java.io.Serializable;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import org.dbp.core.dao.GenericDao;
import org.springframework.transaction.annotation.Transactional;

@Transactional(rollbackFor=Exception.class)
public class GenericDaoImpl  implements GenericDao{

 @PersistenceContext private EntityManager em;
 
 private Class clazzE;

 public GenericDaoImpl(Class clazzE) {
  super();
  this.clazzE = clazzE;
 }

 public E obtenerId(ID id){
  return em.find(clazzE, id);
 }

 public void eliminar(E entidad){
  em.remove(entidad);
 }
 
 public void crear(E entidad){
  em.persist(entidad);
 }
 
 public E actualizar(E actualizar){
  return em.merge(actualizar);
 }
 
 public List obtenerTodos(){
  CriteriaBuilder cb=em.getCriteriaBuilder();
  CriteriaQuery criteria=cb.createQuery(clazzE);
  Root from=criteria.from(clazzE);
  TypedQuery query=em.createQuery(criteria.select(from));
  return query.getResultList();
 }

}

Ejemplo

Una vez definido el dao genérico, para ver todo su potencial es ver el uso y poder apreciar el ahorro de código por un lado, y por otro lado y mas importante que ahora estas operaciones las tenemos centralizadas y si el día de mañana queremos cambiarlas o añadir alguna a todas las entidades lo podemos hacer o cambiar la versión del ORM o lo que sea, nos facilitara la vida.

package org.dbp.dao.impl;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.dbp.bom.Usuario;
import org.dbp.core.dao.impl.GenericDaoImpl;
import org.dbp.dao.UsuarioDao;
import org.springframework.stereotype.Repository;

@Repository
public class UsuarioDaoImpl  
 extends GenericDaoImpl 
 implements UsuarioDao{

 @PersistenceContext private EntityManager em;
 
 public UsuarioDaoImpl() {
  super(Usuario.class);
 }
 
 @Override
 public Usuario obtenerLogin(String login){
  return em.createQuery("from Usuario u where u.login = :login",Usuario.class)
  .setParameter("login", login)
  .getSingleResult();
 }
 
}

Test

Para ver el funcionamiento he creado el siguiente test:

package org.dbp.dao;

import static org.junit.Assert.*;

import java.util.List;

import org.dbp.bom.Usuario;
import org.dbp.core.config.TestConfiguracion;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;

@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
@ContextConfiguration(classes = TestConfiguracion.class)
public class UsuarioDaoTest {

 @Autowired private UsuarioDao usuarioDao;
 
 @Test
 public void testRecuperarTodos(){
  List usuarios=usuarioDao.obtenerTodos();
  assertEquals("Miramos el número de elementos",1,usuarios.size());
 }
 @Test
 public void testObtenerPorId(){
  Usuario usuario=usuarioDao.obtenerId(1L);
  assertEquals("Validamos el ID:",new Long(1L),usuario.getId());
  assertEquals("Validamos el loging","dblanco",usuario.getLogin());
 }

 @Test
 public void testObtenerLogin(){
  Usuario usuario=usuarioDao.obtenerLogin("dblanco");
  assertEquals("Validamos el ID:",new Long(1L),usuario.getId());
  assertEquals("Validamos el loging","dblanco",usuario.getLogin());
 }
}

Conclusión

Yo solo os puedo decir, que en todos los proyectos que hago monto este patrón junto con un servicio desde el año 2007, que lo vi por primera vez.

viernes, 23 de octubre de 2015

Configurar la pagina de login. En Spring security

Uno de los primeros pasos que tenemos que hacer una vez tenemos configurado spring security. Es crear nuestra propia pagina de login.

Creamos la pagina de login:

Lo primero que tenemos que hacer es crear la JSP, que vamos a utilizar como pagina de login.
<c:url value="/" var="contexto" />
<c:url value="/login" var="loginUrl"/>
<head>
 <link href="${contexto}resources/bootstrap/css/bootstrap.min.css" rel="stylesheet">
 <link href="${contexto}resources/bootstrap/css/bootstrap-theme.min.css" rel="stylesheet">
 <link href="${contexto}resources/css/login.css" rel="stylesheet">
</head>
<body>

    <div class="container">
<form action="${loginUrl}" method="post" class="form-signin">   
 <h2 class="form-signin-heading">Login</h2>    

  <label for="username">Usuario</label>
  <input type="text" id="username" name="username" class="form-control"/> 

  <label for="password">Contraseña</label>
  <input type="password" id="password" name="password" class="form-control"/> 

 <input type="hidden"                        
  name="${_csrf.parameterName}"
  value="${_csrf.token}"/>
 <button type="submit" class="btn btn-lg btn-primary btn-block">Conectarse</button>
</div>
</form>

Creamos el mapeo a la pagina de login

Lo siguiente que tenemos que hacer es crear un mapeo a la pagina de login, como en este caso no es necesario crear un controlador, vamos a establecerlo en la configuración de los controladores, como una vista.

@Override
public void addViewControllers(ViewControllerRegistry registry) {
    super.addViewControllers(registry);
    registry.addViewController("/login").setViewName("login");
    registry.setOrder(Ordered.HIGHEST_PRECEDENCE);  
}

Le indicamos a Spring security donde buscar la nueva pagina.

En el post anterior, teníamos puesta la configuración por defecto que es la siguiente:
http
    .authorizeRequests()
        .anyRequest().authenticated()
        .and()
    .formLogin().and()
    .httpBasic();
Ahora lo que vamos hacer es sobrecribir el método de configure y indicar a spring security donde encontrar, la pagina web, en nuestro caso vamos a extender la configuración del formLogin:
  • Indicar donde se encuentra la pagina de login (loginPage)
  • Le damos todos los permisos asociados a loginPage.
@Override
protected void configure(HttpSecurity http) throws Exception {
    super.configure(http);
    http.authorizeRequests()    // Le indicamos que la autorizacion va a ser a nivel de request.
        .anyRequest().authenticated()  // Le indicamos que cada solicitud requiere que el usuario de autentique.
        .and()
    .formLogin()    // Configurar el formato de login.
        .loginPage("/login") // aqui le indicamos donde se encuentra la pagina de login.
        .permitAll();// Aqui le indicamos que la pagina de login es publica.*/
}

Maquetar la pagina login.

Ya que tenemos una pagina de login, la vamos a maquetar con nuestra css para que tengamos una pagina de login acorde con la maquetación de nuestra aplicación. Para este ejemplo he utilizado la siguiente pagina http://getbootstrap.com/examples/signin/ que podéis encontrar en bootstrap.

Permitir que las css de la maquetación, se pueda visualizar.

Para lo siguiente vamos a quitar de la seguridad, la ruta de los /resources/**, para que nuestra pagina de login tenga acceso a ellos:

@Override
 public void configure(WebSecurity web) throws Exception {
     web
      .ignoring()
      .antMatchers("/resources/**");
  super.configure(web);
 }

Con este cambio ya podemos visualizar el login, con su maquetación.

martes, 6 de octubre de 2015

Configurar Spring 4.1 + Spring security


En los artículos anteriores, hemos visto como crear un proyecto web con spring, activar jackson, como establecer diferentes entornos y los contenidos estáticos. Ahora lo que vamos hacer es  configurar la librería de seguridad, para controlar el acceso a nuestra aplicación.
Con la versión actual, al menos por lo que pone la documentación hay que utilizar las dependencias de spring 4.1.6 o podemos tener problemas con el classpath.
En la siguiente URL podeis accedr al ejemplo del articulo: https://github.com/blancoparis-tfc/SpringSeguridad

Añadir la dependencia de spring security.

En este caso vamos a ir a la pagina del proyecto de spring security, para ver a día de hoy cual es la ultima versión, estable, que en nuestro caso sera la versión 4.0.2.REALEASE, podemos observar que es independiente de la versión del core de spring. Esto es debido a que son proyecto independientes en su desarrollo.
Editaremos el fichero de build.gradle y le pondremos la dependencia que nos han pasado.
compile 'org.springframework.security:spring-security-web:4.0.2.RELEASE'
compile 'org.springframework.security:spring-security-config:4.0.2.RELEASE'

Una vez puesta la dependencia podemos observar que el proyecto sigue funcionando, como antes. Ya que por defecto no activa ninguna configuración se seguridad.

Configuración de seguridad.

En este ejemplo vamos a realizar una configuración estándar, que va a consistir en:
  • Toda la web va a ser privada.
  • Los usuarios los vamos a poner en memoria, para realizar las pruebas. (Lo normal es que en producción estén en una B.D o LDAP, y en desarrollo en memoria).
  • Nos logaremos por una pagina web estándar.

Configuración de seguridad.

Para simplificarnos el trabajos y dar claridad a las configuraciones, vamos a crear la configuración de seguridad en una clase separada. 

Para este ejemplo la configuración va a ser bastante simple, ya que solamente vamos a tener que activar la configuración (@EnableWebSecurity) que herede de la clase WebSecurityConfigurerAdapter y por ultimo le vamos a indicar cual es el usuario en memoria para realizar la configuración.
package org.dbp.conf;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity
public class SeguridadConfig extends WebSecurityConfigurerAdapter  {

 @Autowired
 public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
  auth
   .inMemoryAuthentication()
    .withUser("user").password("password").roles("USER");
 }
 
}

Ya tenemos establecida nuestra configuración de seguridad, pero o sorpresa si arrancamos el proyecto, sigue sin funcionar la seguridad. Esto es debido a que nos falta por poner un filtro, que para que funcione necesitamos que el contexto este compartido, para lo cual tenemos que establecerlo en un filtro para que lo compartan todos. (Nos lo va a indicar cuando activemos el filtro).

Ojo: En los ejemplos básico de internet, esta destalle no lo vamos a ver ya que va a estar todo en la misma configuración.

Configurar el contexto compartido


Para poder tener el contexto compartido tenemos que realizar los siguientes cambios, en el web.xml.
  • Configurar el listener: ContextLoaderListener
  • Trasladar el fichero de configuración al listener y quitarlo del servlet. (Poniendo una cadena vacía en contextConfigLocation.
  
   <context-param>
      <param-name>contextClass</param-name>
      <param-value>
         org.springframework.web.context.support.AnnotationConfigWebApplicationContext
      </param-value>
   </context-param>
   <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>org.dbp.conf.WebConfig</param-value>
   </context-param>
  <listener>
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener> 
 

Ahora vemos en el servlet, como quitar le fichero de configuración.
   <init-param>
   <param-name>contextConfigLocation</param-name>
   <param-value></param-value>
  </init-param>
Ya tenemos configurado el contexto, a nivel del contenedor, para que el filtro de seguridad pueda acceder a el.

Ojo con servlet estas configuraciones también se pueden hacer desde clases java tambien.

Configuramos el filtro de seguridad

Aquí simplemente tenemos que crear una clase que herede de AbstractSecurityWebApplicationInitializer. Esta clase si observamos no es un filtro si no un inicializador del contexto de aplicación, que se engancha a nuestro contexto compartido que hemos establecido en el apartado anterior. (Pero al final lo que se configura es un filtro (springSecurityFilterChain) para los temas de la seguridad).
  

package org.dbp.conf;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer  {

}

Enganchar la configuración de seguridad, a la de nuestra aplicación

En este caso es muy fácil simplemente tenemos que establecer, la importación de la configuración. @Import(SeguridadConfig.class) 

Resultado

Una vez realizados los siguientes cambios, que ademas se adaptan adecuadamente a los artículos anteriores, el sistema nos pondrá una pagina de login estándar sin maquetación, para logarse. Aparte según la documentación de spring tendremos las siguiente configuraciones por defecto.

  • Requiere autenticación, por cada URL.
  • Crear el formulario de login.
  • tiene un logout.
  • Prevención de los ataques CSRF-
  • Protecion a (Session Fixation).
  • Integración de la seguridad con la cabecera....
  • Se integran métedo del api Servlet.
    • getRemoteUser.
    • getUserPrincipal
    • isUserInRole
    • login
    • logout

sábado, 5 de septiembre de 2015

Multi-proyecto + Java + Gradle


En un articulo anterior,  ya hemos visto como se puede montar en gradle un multiproyecto, ahora vamos a ver como aplicar esto a un proyecto java dividido en, bom y el service.

Adaptar los sub-proyectos.

Ahora vamos a adaptar los sub-modulos.
  • Establecer la estructura de directorios.
  • Establecemos la configuración común.

Creamos la estructura de directorios

Lo primero será crear la estructura de directorios, en este caso es igual a la que usa maven.
  • /src/main/java
  • /src/main/resources
  • /src/test/java
  • /src/test/resources
Crearemos esta estructura en cada sub modulo.

 

Configurar los módulos

La idea es indicar que los proyectos son de tipo java, en este caso por un lado vamos a configurar la parte común de todos los proyectos, y luego la parte de los sub-proyectos.

Todos los proyectos

- Le indicamos el tipo de proyecto, que en nuestro caso es java y vamos a trabajar con eclipse.
- Aquí estableceremos la versión del proyecto y el grupo que es común para todos los proyectos.
allprojects {
  apply plugin: 'java'
  apply plugin: 'eclipse'
  group = 'org.dbp'
  version = '1.0'
}

En los sub-Modulos.


Aquí vamos a configurar las dependencias.
subprojects{
  repositories {
    mavenCentral()
  }

  dependencies {
   compile 'org.slf4j:slf4j-api:1.7.10'
   compile 'ch.qos.logback:logback-classic:1.1.2'
    testCompile group: 'junit', name: 'junit', version: '4.+'
  }
}

Conclusión


Ahora con estos pequeños cambios ya tenemos el esqueleto pelado para un proyecto java modular.

sábado, 29 de agosto de 2015

Multi-proyecto con gradle


Vamos analizar la necesidad de crear un proyecto, compuesto de varias sub-proyectos.
  • Nos permite realizar una separación lógica de nuestro proyecto. Un clasico es el bom( la B.d), service(La capa de negocio), webapp (La capa de vista).
  • Esta separación nos va evitar que desde un modulo no se puedan llamar a clases del otro ( Si los configuramos como capas separadas). Ejemplo, llamar desde un servicio a la request de un contenedor de servlet que pertenece a la capa de vista.
Cada sub-proyecto va a ser independiente entre si, aunque lo normal es que tenga rasgos comunes.
Ojo: Esto es un ejemplo de como darle utilidad a los subproyectos.
Vamos a ver en este articulo un ejemplo, simple de montar un proyecto raiz y 2 modulos (bom, service).
El ejemplo esta en la siguiente dirección https://github.com/blancoparis-tfc/MultiProyectoGradle.

Organización del fichero.


El proyecto raiz ( o padre), contendrá cada uno de los sub-proyectos (El nombre de la carpeta será el nombre de cada uno de los subProyectos:
Organización del proyecto:
  • build.gradle: El buil del proyecto raiz.
  • settings.gradle: Donde indicaremos los modulos.
  • bom(Directorio): Es el subProyecto  bom.
  • service(Directorio): Es el sub-proyecto service.

Vamos a crear un tarea que nos diga el nombre de cada proyecto, para lo cual nos vamos a apoyar en el buid.gradle del proyecto raiz, vamos a poner una configuración común, de la tarea hola.

Configurar los sub-proyectos.


Ahora le indicamos los sub-proyectos, que en nuestro caso van a ser bom y service.
Fichero (settings.gradle)
include 'bom','service'

Configurar todos los proyectos.


Aquí vamos a ver como establecer la configuración a todos los proyectos.
Fichero (build.gradle)
allprojects {
  task hola << { task -> println "Soy $task.project.name"}
}
$task.project.name—> Accede al nombre del proyecto
La etiqueta allprojects nos pone la configuración en todos los proytectos, incluido el proyecto raiz
Ahora le indicamos los sub-proyectos, que en nuestro caso van a ser bom y service.
Fichero (settings.gradle)
include 'bom','service'
Ahora ejecutamos la tarea hola, ejecutando
gradle –q hola
El resultado es:
>Soy MultiProyectoGradle
>Soy bom
>Soy service

Configurar solo los submodulos


Aqui vamos a ver como establecer la configuración solo para los submodulos, para lo cual vamos a utilizar subprojects.
allprojects {
  task hola << { task -> println "Soy $task.project.name"}
}
subprojects{
  hola << {println "   - Dependo de multi-proyecto"}
}
Ahora ejecutamos la tarea hola, ejecutando
gradle –q hola
El resultado es:
>Soy MultiProyectoGradle
>Soy bom
>    - Dependo de multi-proyecto
>Soy service
>    - Dependo de multi-proyecto

Establecer un comportamiento especifico a un proyecto.


Ahora vamos a verr, como podemos indicar una configuración especifica a un sub-proyecto en cuestión, para lo cual vamos a usar project('<nombre del sub-proyecto).<tarea>
allprojects {
  task hola << { task -> println "Soy $task.project.name"}
}
subprojects{
  hola << {println "   - Dependo de multi-proyecto"}
}
project(':bom').hola << {
  println "        - Soy el proyecto  donde va a estar el modelo de dominio "
}
Ahora ejecutamos la tarea hola, ejecutando
gradle –q hola
>Soy MultiProyectoGradle
>Soy bom
>    - Dependo de multi-proyecto
>          - Soy el proyecto donde va a estar el modelo de dominio
>Soy service
>    - Dependo de multi-proyecto

Nota: La configuración del modulo, lo idea es que este en su propio scripts del proyecto, pero asi vemos como podemos establecer la configuración desde el modulo raiz.

Configurar los sub-proyectos


Ahora vamos a ver como configurar cada sub-modulo, con su propio scripts de gradle

/bom/build.gradle
hola.doLast {
  println "             - Soy el proyecto donde vamos a definir el modelo de dominio";
}
/service/build.gradle
hola.doLast {
  println "             - Soy el proyecto que implementa la capa de negocio";
}
Ahora ejecutamos la tarea hola, ejecutando
gradle –q hola
>Soy MultiProyectoGradle
>Soy bom
>    - Dependo de multi-proyecto
>          - Soy el proyecto donde vamos a definir el modelo de dominio
>Soy service
>    - Dependo de multi-proyecto
>          - Soy el proyecto que implementa la capa de negocio

Reglas de ejecución:


En este caso sigue la regla de ejecutar todas las tareas que se encuentren en la jerarquía, hacia abaojo, por lo cual si entramos en el directorio bom, solo ejecutara la de bom. 

 bom/gradle –q hola

>Soy bom
>    - Dependo de multi-proyecto
>          - Soy el proyecto donde vamos a definir el modelo de dominio

El orden de ejecución es el alfabetico por defecto segun los encuentra  en la jerarquia, por lo cual en el nivel inferior, (ejecuta el multi-proyecto (nivel 0), luego bom y service.

Establecer el orden de ejecución:


Como hemos visto en los ejemplos anteriores, el orden de ejecución es el raiz y el resto por orden alfabetico.

Aunque en este caso no lo necesitamos vamos a ver como establecer un orden de ejecución entre los diferentes sub-proyectos.

Para este ejemplo crearemos la tarea inverso y en le proyecto bom, le vamos a indicar que esta tarea le precede el service, para lo cual utilizaremos el atributo dependsOn

/bom/build.gradle
hola.doLast {
  println "             - Soy el proyecto donde vamos a definir el modelo de dominio";
}
task inverso(dependsOn: ":service:inverso") <<{
  println " El ultimo es bom";
}
/service/build.gradle
hola.doLast {
  println "             - Soy el proyecto que implementa la capa de negocio";
}
task inverso <<{
  println " El primero es service";
}
gradle –q inverso
> El primero es service
> El ultimo es bom

Conclusión

En este articulo hemos visto con unos ejemplos tontos diferentes comportamientos, a la hora de trabajar con un proyecto en gradle por módulos, sin meter ninguna complicación mas. Para realizarlo me he basado en la documentación de gradle oficial, donde vienen muchas mas cosas en el siguiente enlace (https://docs.gradle.org/current/userguide/multi_project_builds.html#multiprojectUseSubprojects)

Nota: En la documentación oficial de gradle hay muchas mas cosas, como mecanismos para filtrar etc...