JPA, ejemplo de anotaciones

Cuando programamos en Java muchas veces tenemos la necesidad de hacer uso de bases de datos. Anteriormente se usaba (aunque algunos lo siguen usando) JDBC. No obstante, el uso de JPA es lo más usual hoy en día.

Imaginemos que tenemos dos tablas Empleado y Departamento con sus respectivos campos. Para enlazar nuestra aplicación no solo es necesario contar con los drivers necesarios para establecer la conexión a las bases de datos (MySQL, Postgresql, Oracle, etc.), también es indispensable establecer la lógica de las entidades.

Empleado dependerá de un Departamento, por ejemplo, Sistemas para los programadores y Contabilidad para los contadores. La entidad Departamento puede tener más de un empleado, pero la entidad Empleado no puede pertenecer a más de un departamento.

¿Cómo podemos crear una relación entre éstas dos entidades?

Para ello tenemos las anotaciones JPA.
@OneToMany , para establecer una relación de uno a muchos. Ideal para Departamento.
@ManyToOne, para establecer una relación de muchos a uno. Para Empleado que sólo puede pertenecer a un departamento.
La anotación @JoinColumn nos servirá para definir la clave externa (la del departamento).

c2cd9-seleccic3b3n_008

Pasemos a la codificación de las entidades.

Tenemos a Empleado.

Empleado.java

package com.codemonkey.model;

import javax.persistence.*;

@Entity
@Table(name="empleado")
public class Empleado implements java.io.Serializable{
  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  @Column(name="idempleado")
  private int idempleado;

  @ManyToOne
  @JoinColumn(name="iddepartamento")
  private Departamento departamento;
  //constructores
  //métodos de acceso
}

@Id, indica la llave primaria

@GeneratedValue(strategy=GenerationType.AUTO), esto índica que la clave será auto incrementable.

@Column, nos sirve para especificar el nombre de la columna en nuestra tabla de información.

Ahora tenemos a Departamento.

Departamento.java

package com.codemonkey.model;

import javax.persistence.*;
import java.util.List;

@Entity
@Table(name="departamento")
public class Departamento implements java.io.Serializable{
  @Id
  @Column(name="iddepartamento")
  private int iddepartamento;

  @OneToMany(mappedBy="departamento")
  private List empleados;
  //constructores
  //métodos de acceso
}

Advertisements

Clases en Python

ec564-shomecode4

Programar en Python puede parecer complejo para ciertas personas. Sin embargo, para muchas otras es muy fácil.

Para muestra pasa un botón (una clase):

persona.py

class Persona(object):
     pass

Esta clase (Persona) puede terner atributos:

  • nombre
  • apellidos
  • edad
  • dirección
  • email
  • teléfono
class Persona(object):
	def __init__(self, nombre,apellidos,edad, direccion, email,telefono):
		self.nombre=nombre
		self.apellidos=apellidos
		self.edad=edad
		self.direccion=direccion
		self.email=email
		self.telefono=telefono
		print "Objeto Persona creado e inicializado"

¿Así de fácil? Sí. Y más. ¿Podemos crear herencia? Claro. Crearemos una clase hija denominada Empleado con dos atributos (puesto y horas laboradas).

class Empleado(Persona):
	def __init__(self,puesto,horas,nombre,apellidos,edad, direccion, email, telefono):
		super(Empleado,self).__init__(nombre,apellidos,edad, direccion, email, telefono)
		self.puesto=puesto
		self.horas=horas
		print "Objeto Empleado creado e inicializado"

La clase Empleado no solo tendrá su propios atributos sino que también heredará atributos de la case padre (Persona).

La instanciación es similar a la usada en lenguajes como Java.

def main():
#Persona
	my_persona = Persona("Genaro","Moreno",36, "Aldama no. 333, Toluca, Edo. Mex.","genaro@hotmail.com","444-555-00")
	print "Nombre:",my_persona.nombre
	print "Apellidos:",my_persona.apellidos
	print "Edad:",my_persona.edad
	print "Direccion:",my_persona.direccion
	print "Email:",my_persona.email
	print "Telefono:",my_persona.telefono

#Empleado
	my_empleado = Empleado("Administrador", 12, "Adrian","Chavez",45,"Juarez no. 55, Ecatepec","chavez@latinmail.com","555-998-00")
	print "Puesto:",my_empleado.puesto
	print "Horas trabajadas:",my_empleado.horas
	print "Nombre:",my_empleado.nombre
	print "Apellidos:",my_empleado.apellidos
	print "Edad:",my_empleado.edad
	print "Direccion:",my_empleado.direccion
	print "Email:",my_empleado.email
	print "Telefono:",my_empleado.telefono

#Método main
if __name__ == '__main__':
	main()

Links:
http://codemonkeyjunior.blogspot.mx

Servicio REST Api con Spring Data

Creamos un Proyecto Nuevo en https://start.spring.io/

Elegiremos Maven para la creación del ejemplo.

Screenshot_1

En la sección SQL elegimos JPA y PostgreSQL.

Screenshot_2

En la sección WEB elegimos Web y Rest Repositories

Screenshot_3

Finalizamos y descargamos el ejemplo. Debe quedar así en nuestro directorio.

Screenshot_4

Abrimos una terminal en el directorio y tecleamos:

mvn clean install

Maven se encargará de descargar las librerías necesarias para el proyecto.

Agregamos plugin para Eclipse IDE

mvn eclipse:eclipse

Ahora abrimos Eclipse e importamos proyecto Maven existente

Screenshot_5

Elegimos nuestro proyecto

Screenshot_6

Revisamos dependencias necesarias en el pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.codemonkey</groupId>
    <artifactId>api-rest</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>api-rest-ejemplo</name>
    <description>Uso de API Rest Spring Data</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope> </dependency> -->
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project><span 				data-mce-type="bookmark" 				id="mce_SELREST_start" 				data-mce-style="overflow:hidden;line-height:0" 				style="overflow:hidden;line-height:0" 			></span>

Creamos una tabla alumno.
Screenshot_7

Insertamos valores.

INSERT INTO public.alumno(nombre, apellidos, direccion, telefono, email)
	VALUES ('Zuzanne', 'Waller', 'Tomahawk no. 100', '555-766', 'zuzanewll@gmail.com'),('Yohanan', 'Diaz', 'Toluca, Edo. Mex.', '555-111', 'genaro.amaro@latinmail.com');

Screenshot_8

Creamos clase Alumno.java

package com.codemonkey.entity;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Id;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Column;

@Entity
@Table(name="alumno")
public class Alumno implements Serializable{
	private static final long serialVersionUID = 1L;
	@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
	private int id;
	@Column(name = "nombre")
	private String nombre;
	@Column(name = "apellidos")
	private String apellidos;
	@Column(name = "direccion")
	private String direccion;
	@Column(name = "telefono")
	private String telefono;
	@Column(name = "email")
	private String email;

	public Alumno() {}

	public Alumno(int id, String nombre, String apellidos, String direccion, String telefono, String email) {
		super();
		this.id = id;
		this.nombre = nombre;
		this.apellidos = apellidos;
		this.direccion = direccion;
		this.telefono = telefono;
		this.email = email;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getNombre() {
		return nombre;
	}

	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	public String getApellidos() {
		return apellidos;
	}

	public void setApellidos(String apellidos) {
		this.apellidos = apellidos;
	}

	public String getDireccion() {
		return direccion;
	}

	public void setDireccion(String direccion) {
		this.direccion = direccion;
	}

	public String getTelefono() {
		return telefono;
	}

	public void setTelefono(String telefono) {
		this.telefono = telefono;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@Override
	public String toString() {
		return "Alumno [id=" + id + ", nombre=" + nombre + ", apellidos=" + apellidos + ", direccion=" + direccion
				+ ", telefono=" + telefono + ", email=" + email + "]";
	}

}

Creamos un Repositorio de datos

package com.codemonkey.repository;

import org.springframework.data.repository.PagingAndSortingRepository;

import com.codemonkey.entity.Alumno;

public interface AlumnoRepository extends PagingAndSortingRepository<Alumno, Integer>{
}

Clases principales de la aplicación.
ApiRestEjemploApplication.java

package com.codemonkey;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ApiRestEjemploApplication {

	public static void main(String[] args) {
		SpringApplication.run(ApiRestEjemploApplication.class, args);
	}
}

SpringApplicationBuilder.java

package com.codemonkey;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;

public class ServletInitializer extends SpringBootServletInitializer {

	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
		return application.sources(ApiRestEjemploApplication.class);
	}

}

application.properties

spring.data.rest.basePath=/api

#MySQL
#spring.datasource.url=jdbc:mysql://localhost:3306/proyecto
#spring.datasource.username=root
#spring.datasource.password=root
#spring.datasource.driver-class-name=com.mysql.jdbc.Driver

#POSTGRESQL
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/proyecto
spring.datasource.username=postgres
spring.datasource.password=5432
#spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.hibernate.ddl-auto=update
#spring.jpa.hibernate.ddl-auto=create
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy

# JPA (JpaBaseConfiguration, HibernateJpaAutoConfiguration)
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect

Ejecutamos la aplicación y abrimos el navegador en la dirección

http://localhost:8080/api/alumnoes

Links:

https://geeks-mexico.com/2018/01/04/crea-un-api-rest-de-la-forma-mas-simple-con-java-y-spring-data-rest/

https://start.spring.io/

Instalando Spring y Gradle en Eclipse

¿Qué necesitamos? Descargar Eclipse for Java EE Developers aquí: http://www.eclipse.org/downloads

Una vez abierto el ide. Ir a la pestaña Help y elegir Eclipse Marketplace. Teclear Spring Framework y dar enter. Elegir Spring Tools.

Screenshot_1

Dar clic en botón Install. Se inicializará la instalación:

Screenshot_2

Confirmar y finalizar:

Screenshot_3

Finalizar:

Screenshot_4

Comprobamos instalación:

Screenshot_5

Instalando Gradle.

Help -> Marketpplace y teclear Gradle. Elegir Buildship Gradle Integration y dar clic en Install. También podemos elegir el editor Gradle.

Screenshot_6

El proceso finalizará y reiniciamos el IDE.

 

Javascript … uso de prototype

Selección_762

Hoy hablaremos de Javascript. Como crear clases y objetos. Además del uso de prototype, una característica del lenguaje javascript que nos permite extender los métodos o atributos de una clase previamente definida.

Crearemos un archivo clases.js y escribiremos el siguiente código:

var Computadora = function(sistema_operativo, modelo, marca){
     this.sistema_operativo=sistema_operativo;
     this.modelo=modelo;
     this.marca=marca;
};

En este ejemplo definimos una clase llamada Computadora y tres atributos: sistema_operativo, modelo y marca. Pero ¿qué pasa si quiero agregar más atributos? Lo sencillo sería agregarlos, pero ¿y si ese código está dentro de un archivo *.js al cual no puedo modificar? Para eso usamos prototype.

Síntaxis:

Clase.prototype.atributo
Clase.prototype.método

Tenemos así:


//Agregando/extendiendo atributos

Computadora.prototype.dns='';

Computadora.prototype.ip='';

Computadora.prototype.red='';

//Agregando/extendiendo métodos

Computadora.prototype.verComputadora=function(computadora){

var objetoC= 'Computadora 
Modelo: '+computadora.modelo
+"
Marca: "+computadora.marca+"
Sistema operativo: "+computadora.sistema_operativo
+"
IP:" +computadora.ip+"
DNS: "+computadora.dns
+"
RED: "+computadora.red;

document.getElementById('comp').innerHTML= objetoC;

}

¿Cómo creo una instancia?

function crearComputadora(){

var computadora = new Computadora('Linux','HP vPro','HP');

computadora.ip='148.216.33.21';

computadora.dns='148.216.60.1';

computadora.red='Infinitum';

return computadora;

}

Ahora para obtener ese objeto.

var obtenerComputadora = function(){
   var comp= crearComputadora();
   comp.verComputadora(comp);
};

Dentro de una página HTML crearemos un botón y le añadiremos un evento ‘click’:

<button id='btn'>Obtener</button>

Finalmente el evento:

document.getElementById('btn').addEventListener('click', obtenerComputadora);

Links:
http://lineadecodigo.com/javascript/programacion-orientada-a-objetos-con-javascript-un-sencillo-ejemplo/

Spring MVC … primer ejemplo (REST)

Para este ejemplo crearemos una base de datos (yo uso postgresql) llamada proyecto, agregaremos una tabla usuario con los siguientes campos: id, nombre, password, logeado y area.

CREATE TABLE public.usuario
(
    id integer NOT NULL,
    nombre character varying NOT NULL,
    password character varying  NOT NULL,
    logeado boolean,
    area character varying,
    CONSTRAINT usuario_pkey PRIMARY KEY (id)
);

Ahora agregaremos unos datos:

INSERT INTO public.usuario(
	id, nombre, password, logeado, area)
	VALUES (1, 'Antony Yung', 00T$@l12', true, 'sistemas'),(2, 'Adrian Uribe', '3EvBb00', false, 'administracion'),
    (3,'Ernestina Pedroza','@22GgHQll',true,'recursos humanos');

Una vez creado la base de datos y su correspondiente tabla nos enfocaremos a crear el ejemplo con Spring MVC.

¿Qués es lo que necesitaremos?

  1. Archivo: build.gradle , para configurar las dependencias necesarias
  2. Archivo: application.properties, para configurar el acceso a la BD,entre otras cosas
  3. Dentro del paquete controller: UsuarioRestController.java y MainController.java
  4. Dentro del paquete config: WebSecurityConfig.java y MvcConfig.java
  5. Dentro del paquete entity: Usuario.java
  6. Dentro del paquete repository: UsuarioRepository.java
  7. Dentro del paquete service: UsuarioService.java y UsuarioServiceImpl.java
  8. Dentro de la subcarpeta src/main/resouces/templates: test_template.html , home.html , login.html y hello.html
  9. Dentro de la carpeta src/main/resources/static/js el archivo *.js: datatable.js (https://datatables.net/)

Comencemos

Este archivo nos servirá para configurar las dependencias necesarias pra nuestro proyecto (acceso a web, security, bases de datos, en este caso postgresql, etc.)

build.gradle

/**
*
*
*@description Ejemplo
*@version 1.1.0
*
*
*
* 1. Construir proyecto: gradle build
* 2. Ver tareas disponibles: gradle task
* 3. Ejecutar: gradle run รณ gradle bootRun
*/

buildscript {

        ext {
                springBootVersion = '1.5.6.RELEASE'
        }

        repositories {
                mavenCentral()
                maven {
                        url "https://plugins.gradle.org/m2/"
                }
        }
        dependencies {
                classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        }
}

apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'war'
apply plugin: 'eclipse-wtp'
apply plugin: 'project-report'
apply plugin: 'org.springframework.boot'

version = '1.0.0'
sourceCompatibility = 1.8
targetCompatibility = 1.8
mainClassName = "com.codemonkey.Application"
description ="""
Ejemplo de proyecto hecho con Gradle build

"""

jar {

        baseName='principal'

        manifest{
                attributes 'Main-Class': 'com.codemonkey.Application'
        }
}

repositories {
        mavenCentral()
}

dependencies {
        compile('org.springframework.boot:spring-boot-starter')
        compile('org.springframework.boot:spring-boot-starter-web')
		compile('org.springframework.boot:spring-boot-starter-actuator')
		compile('org.springframework.boot:spring-boot-starter-thymeleaf')
		providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
		testCompile group: 'org.slf4j', name: 'slf4j-log4j12', version: '1.7.25'
		compile("com.fasterxml.jackson.core:jackson-databind")
		compile("org.springframework.boot:spring-boot-starter-data-jpa")
		compile("org.springframework.boot:spring-boot-starter-data-rest")
		runtime('org.postgresql:postgresql')
		compile("org.springframework.boot:spring-boot-starter-security")
}

configurations.all {
    resolutionStrategy.cacheDynamicVersionsFor 10, 'minutes'
}

project.configurations.compile.resolvedConfiguration.resolvedArtifacts.each {
 println '   [Dependencias] '
 println 'artifact: '+it.name
 println 'referencia: '+it.file
 println '**************************'
}

Este archivo se usará para configurar el acceso a la base de datos en postgresql, indicar el uso de las plantillas Thymeleaf.
application.properties

#BANNER
banner.charset=UTF-8
banner.location=banner.txt

#THYMELEAF TEMPLATES
spring.thymeleaf.cache=false
spring.thymeleaf.check-template=true
spring.thymeleaf.check-template-location=true
spring.thymeleaf.content-type=text/html
spring.thymeleaf.enabled=true
spring.thymeleaf.encoding=UTF-8
#spring.thymeleaf.excluded-view-names= # Comma-separated list of view names that should be excluded from resolution.
#spring.thymeleaf.mode=HTML5 # Template mode to be applied to templates. See also StandardTemplateModeHandlers.
#spring.thymeleaf.prefix=classpath:/templates/ # Prefix that gets prepended to view names when building a URL.
spring.thymeleaf.suffix=.html
#spring.thymeleaf.template-resolver-order= # Order of the template resolver in the chain.
#spring.thymeleaf.view-names= # Comma-separated list of view names that can be resolved.

#POSTGRESQL
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/proyecto
spring.datasource.username=postgres
spring.datasource.password=5432
#spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.hibernate.ddl-auto=update
#spring.jpa.hibernate.ddl-auto=create
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy

# JPA (JpaBaseConfiguration, HibernateJpaAutoConfiguration)
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect

No debemos olvidar las clases principales del programa: Application.java y ServletInitializer.java
ServletInitializer.java

package com.codemonkey;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;

public class ServletInitializer extends SpringBootServletInitializer {

	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
		return application.sources(Application.class);
	}

}

Application.java

package com.codemonkey;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

Nuestro @Controller principal.
MainController.java.java

package com.codemonkey.controller;

import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@Controller
public class MainController {

      @RequestMapping(path="/", method=RequestMethod.GET)
	public String goHome(){
		return "index";
	}

}

El @RestController de la aplicación.
UsuarioRestController.java

package com.codemonkey.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;

import com.codemonkey.entity.Usuario;
import com.codemonkey.service.UsuarioService;

@RestController
@RequestMapping("/testUsuarios")
public class UsuarioRestController {

	@Autowired
	private UsuarioService usuarioService;

	//REST
    //http://localhost:8080/testUsuarios/usuarios
	@RequestMapping(path="/usuarios", method=RequestMethod.GET)
	public List<Usuario> getAllUsuarios(){
		return usuarioService.getAllUsuarios();
	}

	//http://localhost:8080/testUsuarios/usuario/1/
    @RequestMapping(value = "/usuario/{id}", method = RequestMethod.GET)
	public Usuario getUsuarioById(@PathVariable("id") long id){
		return usuarioService.getUsuarioById(id);
	}

	//http://localhost:8080/testUsuarios/testUsuarios
	@GetMapping("/testUsuarios")
    public ModelAndView test_template(){
        ModelAndView mav= new ModelAndView("test_template");
        return mav;
    }

}

El @Configuration de seguridad, donde indicamos el usuario y clave de acceso (root/123)
WebSecurityConfig.java

package com.codemonkey.config;

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

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }

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

El @Configuration de vistas home -> login -> hello.
MvcConfig.java

package com.codemonkey.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/home").setViewName("home");
        registry.addViewController("/").setViewName("home");
        registry.addViewController("/hello").setViewName("hello");
        registry.addViewController("/login").setViewName("login");
    }

}

La clase Entidad que servirá para enlazar los datos de la tabla ‘usuario’.

Usuario.java

package com.codemonkey.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Usuario {
	@Id
	@GeneratedValue
	@Column(name="id")
	private long id;
	@Column(name="nombre")
	private String nombre;
	@Column(name="password")
	private String password;
	@Column(name="logeado")
	private boolean logeado;
	@Column(name="area")
	private String area;

	public Usuario(){super();}

	public Usuario(String nombre, String password,
	boolean logeado, String area){
		super();
		this.nombre=nombre;
		this.password=password;
		this.logeado=logeado;
		this.area=area;
	}

	public void setId(long id){
		this.id=id;
	}

	public long getId(){
		return id;
	}

	public void setNombre(String nombre){
		this.nombre=nombre;
	}

	public String getNombre(){
		return nombre;
	}

	public void setPassword(String password){
		this.password=password;
	}

	public String getPassword(){
		return password;
	}

	public void setLogeado(boolean logeado){
		this.logeado=logeado;
	}

	public boolean isLogeado(){
		return logeado;
	}

	public void setArea(String area){
		this.area=area;
	}

	public String getArea(){
		return area;
	}

}

El @Repository, para hacer uso de los métodos necesarios para manipular los datos.
UsuarioRepository.java

package com.codemonkey.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.codemonkey.entity.Usuario;

@Repository("usuarioRepository")
public interface UsuarioRepository extends JpaRepository<Usuario, Long>{

}

La interface que nos permite crear métodos para obtener los registros de la tabla ‘usuario’.
UsuarioService.java

package com.codemonkey.service;

import java.util.List;

import com.codemonkey.entity.Usuario;

public interface UsuarioService {

	public List<Usuario> getAllUsuarios();
	public Usuario getUsuarioById(long id);

}

Esta clase nos permitirá descoplar el código.
UsuarioServiceImpl.java

package com.codemonkey.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.codemonkey.entity.Usuario;
import com.codemonkey.repository.UsuarioRepository;

@Service("usuarioService")
public class UsuarioServiceImpl implements UsuarioService {

	@Autowired
	private UsuarioRepository usuarioRepository;

	@Override
	public List<Usuario> getAllUsuarios() {
		return usuarioRepository.findAll();
	}

	@Override
	public Usuario getUsuarioById(long id) {
		return usuarioRepository.findOne(id);
	}

}

Ahora pasemos a los templates o vistas.

Página de bienvenida.
home.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Bienvenido</title>
        <style type="text/css">
           #centro {
    margin: auto;
    width: 50%;
    border: 0.8em solid #2f5777;
    padding: 10px;
}

h1{
    text-align: center;
}
        </style>
    </head>
    <body>
<div id="centro">
<h1>Bienvenido</h1>
Da clic en el  <a th:href="@{/hello}">enlace</a> para entrar.</div>
</body>
</html>

Página de login (root/123) para acceder la vista hello.
login.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Formulario de entrada </title>
<style type="text/css">
   #centro {
    margin: auto;
    width: 50%;
    border: 0.8em solid #2f5777;
    padding: 10px;
}

#my_input{
    border: 1px solid #2f5777;
    font-size: medium;
    background-color: #2f5777;
    color: white;
}

h1{
    text-align: center;
}

</style>
    </head>
    <body>
<div th:if="${param.error}" id="centro">
            Nombre de usuario y/o clave incorrectos.</div>
<div th:if="${param.logout}" id="centro">
            Logeado.</div>
<div id="centro">
<h1>Formulario de entrada</h1>
<form th:action="@{/login}" method="post">
<div><label> Nombre de usuario : <input type="text" name="username"/> </label></div>
<div><label> Clave de acceso: <input type="password" name="password"/> </label></div>
<div><input type="submit" value="Entrar" id="my_input"/></div>
</form></div>
</body>
</html>

La página hello.html nos permitirá acceder a nuestro ejemplo.
hello.html

<!DOCTYPE html>
 <html lang="es">
 <head>
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
   <meta name="viewport" content="width=device-width, initial-scale=1"/>
        <title>Has entrado</title>
        <script type="text/javascript" src="/js/funciones.js"></script>
        		<link rel="stylesheet" type="text/css" media="all" href="css/estilos.css" th:href="@{css/estilos.css}" />

        		<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"/>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    		<link rel="stylesheet" href="https://cdn.datatables.net/1.10.12/css/jquery.dataTables.min.css"/>
    <script src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script>
    <script src="/js/datatable.js"></script>
        </head>
    <body>


<div id="centro">


<h1>Bienvenido</h1>


Hola [[${#httpServletRequest.remoteUser}]]!
           <form th:action="@{/logout}" method="post">
            <input type="submit" value="Salir" id="my_input"/>
        </form>
</div>


Da clic <a th:href="@{/testUsuarios/testUsuarios}">aquí</a> para entrar y ver los usuarios.
    </body>
</html>

Esta página muestra una tabla con los datos de los usuarios registrados en la tabal ‘usuario’.
test_template.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="utf-8" />
	<title>Spring Boot + JPA + Datatables</title>
			<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"/>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
	<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
			<link rel="stylesheet" href="https://cdn.datatables.net/1.10.12/css/jquery.dataTables.min.css"/>
	<script src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script>
	<script src="/js/datatable.js"></script>
</head>

<body>
<h1>Usuarios</h1>
<table id="usuariosTable" class="display">
<thead>
<tr>
<th>Id</th>
<th>Nombre</th>
<th>Password</th>
<th>Logeado</th>
<th>Área</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Id</th>
<th>Nombre</th>
<th>Password</th>
<th>Logeado</th>
<th>Área</th>
</tr>
</tfoot>
</table>
</body>
</html>

Este archivo *.js nos permite recoger los datos del JSON creado y desplegarlo en una tabla html
datatable.js

$(document).ready( function () {
	 var table = $('#usuariosTable').DataTable({
			"sAjaxSource": "/testUsuarios/usuarios",
			"sAjaxDataProp": "",
			"order": [[ 0, "asc" ]],
			"aoColumns": [
			    { "mData": "id"},
		      { "mData": "nombre" },
				  { "mData": "password" },
				  { "mData": "logeado" },
				  { "mData": "area"},
			]
	 })
});

Construir:

gradle build

Ejecutar:

gradle bootRun

Visualizar:
http://localhost:8080/testUsuarios/usuarios
Saldrá la página de bienvenida, debes dar clic en el enlace y aparecerá el formulario, introduce el usuario (root) y clave (123). Al acceder debes dar clic en el enlace y ver el resultado.

Spring MVC

¿Qué es Spring Framework?

Es un marco de trabajo que se apoya en algunos estándares Java EE para el desarrollo de aplicaciones y contenedor de inversión de control. Nos permite, entre otras cosas, crear aplicaciones web, servicios REST, persistencia de bases de datos relacionales y no relacionales, etc. En este post hablaremos de Spring MVC, el cual es un marco de trabajo que nos permite crear aplicaciones web con la arquitectura MVC.

Arquitectura Modelo-Vista-Controlador (Model-View-Control)

Esta arquitectura se compone de tres principales conceptos:

  • A. Modelo: Objetos Java.
  • B. Vista: Plantilla que genera la HTML.
  • C. Controlador: Controlador que atiende las peticiones HTTP que llegan al servidor desde el navegador; si resuelve la petición, devuelve una respuesta, en este caso la página HTML.

Supongamos que un cliente quiere saber el estado actual de sus movimientos bancarios.

  1. El cliente hace una solicitud al servidor.
  2. El servidor atiende esa solicitud, verifica si puede atenderla y en caso afirmativo prepara un objeto.
  3. Ese objeto contiene los datos solicitados y con eso el controlador genera una vista (HTML) que verá el cliente en su pantalla.

¿Por qué usar Spring MVC en vez de otras tecnologías (EJB)?
Eso es cuestión de enfoques y necesidades del desarrollador (o jefes del desarrollador).

¿Qué necesito saber para aprender Spring MVC?
Comprender la lógica de la programación (principalmente la orientada a objetos). Entender qué son los patrones de diseño (IoC= Inversión de Control) y comprender como funciona el protocolo HTTP y los métodos GET y POST. Y un sinfín de cosas más.

¿Qué herramientas necesito para comenzar?
Por el momento dos cosas:

  1. Un editor de textos
  2. Descargar e instalar Gradle

Comencemos. Crearemos un proyecto llamado Test. Con la siguiente estructura de directorios:

Test/src/main/java
Test/src/main/resources

Carpeta src/main/java

src/main/java/com/codemonkey/Application.java
src/main/java/com/codemonkey/model/Usuario.java
src/main/java/com/codemonkey/controller/ControllerUsuario.java

Carpeta src/main/resources

src/main/resources/templates
src/main/resources/static
src/main/resources/application.properties
src/main/resources/banners.txt

Para descargar e instalar Gradle podemos usar SKDMAN!
$ sdk install gradle

Una vez instalado crearemos un archivo *.gradle. Este archivo contendrá las dependencias necesarias para crear nuestro ejemplo (disculpen si no lo describo detalladamente).

build.gradle

/**
*
*
*@description Ejemplo
*@version 1.1.0
*
*
*
* 1. Construir proyecto: gradle build
* 2. Ver tareas disponibles: gradle task
* 3. Ejecutar: gradle run ó gradle bootRun
*/

buildscript {

ext {
springBootVersion = '1.5.6.RELEASE'
}

repositories {
mavenCentral()
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}

apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'war'
apply plugin: 'eclipse-wtp'
apply plugin: 'project-report'
apply plugin: 'org.springframework.boot'

version = '1.0.0'
sourceCompatibility = 1.8
targetCompatibility = 1.8
mainClassName = "com.codemonkey.Application"
description ="""
Ejemplo de proyecto hecho con Gradle build

"""

jar {

baseName='principal'

manifest{
attributes 'Main-Class': 'com.codemonkey.Application'
}
}

repositories {
mavenCentral()
}

dependencies {
compile('org.springframework.boot:spring-boot-starter')
compile group: 'org.projectlombok', name: 'lombok', version: '1.16.16'
testCompile('org.springframework.boot:spring-boot-starter-test')
compile('org.springframework.boot:spring-boot-starter-mustache')
compile('org.springframework.boot:spring-boot-starter-web')

}

configurations.all {
resolutionStrategy.cacheDynamicVersionsFor 10, 'minutes'
}

//Ver dependencias
project.configurations.compile.resolvedConfiguration.resolvedArtifacts.each {
println ' [Dependencias] '
println 'artifact: '+it.name // << the artifact name
println 'referencia: '+it.file // << the file reference
println '**************************'
}

Ejemplo. Crearemos un servicio REST sencillo con las clases Usuario y Area.

  1. Clase principal: Application.java
  2. Clase Usuario.java
  3. Clase Area.java
  4. Controlador ControllerUsuario.java

Application.java


package com.codemonkey;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

}

Usuario.java

package com.codemonkey.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Setter;
import lombok.Getter;

@Data
@AllArgsConstructor
public class Usuario{
@Getter @Setter private int id;
@Getter @Setter private String nombre_usuario;
@Getter @Setter private String password;
@Getter @Setter private boolean logeado;
@Getter @Setter private Area area;
}

Area.java

package com.codemonkey.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Setter;
import lombok.Getter;

@Data
@AllArgsConstructor
public class Area {
@Getter @Setter private int id;
@Getter @Setter private String responsable_area;
@Getter @Setter private int piso;
}

Como pueden notar nos ayudamos de Lombok para generar los getter y setter de ambas clases.

ControllerUsuario.java

package com.codemonkey.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Date;

import com.codemonkey.model.Usuario;
import com.codemonkey.model.Area;

@RestController
@RequestMapping("/nodo")
public class ControllerUsuario {

//http://127.0.0.1:8080/nodo/usuarios
@RequestMapping("/usuarios")
public List getUsuarios(){
List listaUsuario = new ArrayList();
listaUsuario.add(new Usuario(1, "Sr. Negativo", "1234", true, new Area(1, "sistemas",10)));
listaUsuario.add(new Usuario(2, "OscarRyz", "ryz123", false, new Area(2, "informatica",12)));
listaUsuario.add(new Usuario(3, "Benek", "secreta", true, new Area(3, "manager",9)));
return listaUsuario;
}

}

Construimos el proyecto:

$ gradle build

Ejecutamos:

$ gradle bootRun

Abrimos cualquier navegador en la siguiente dirección:
http://127.0.0.1:8080/nodo/usuarios

Cabecera de la respuesta

Content-Type application/json;charset=UTF-8
Date Sun, 13 Aug 2017 02:19:22 GMT
Transfer-Encoding chunked

Cabeceras de la petición

Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language en-US,en;q=0.5
Connection keep-alive
Host 127.0.0.1:8080
Upgrade-Insecure-Requests 1
User-Agent Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:54.0) Gecko/20100101 Firefox/54.0

Datos obtenidos:

[{“id”:1,”nombre_usuario”:”Sr. Negativo”,”password”:”1234″,”logeado”:true,”area”:{“id”:1,”responsable_area”:”sistemas”,”piso”:10}
},
{“id”:2,”nombre_usuario”:”OscarRyz”,”password”:”ryz123″,”logeado”:false,”area”:{“id”:2,”responsable_area”:”informatica”,”piso”:12}
},
{“id”:3,”nombre_usuario”:”Benek”,”password”:”secreta”,”logeado”:true,”area”:{“id”:3,”responsable_area”:”manager”,”piso”:9}}
]

Nota: Firefox muestra mejor esos datos.

Ejemplo de inversión de control en Java

robotics-2180263_1920

Supongamos que tenemos varios módulos y todos requieren usar un mismo servicio o recurso. ¿Qué hacemos? ¿Escribimos líneas y más líneas de código para hacer exactamente las mismas tareas? Podría ser. Pero sería muy tedioso. Para ahorrar escribir y escribir lo mismo podemos optar por usar patrones de diseño.

Inversión de control (for Dummies):

Básicamente es un patrón de diseño que nos permite desacoplar unos módulos de otros.

Ejemplo. Crearemos una interface (una clase puramente abstracta en Java) y dos clases que la implementen, después una clase llamada Contenedor que hará uso de esa interface y tendrá sus propios métodos. Finalmente una clase principal llamada Main que servirá para ejecutar la aplicación.

Servicio.java

/**
*
*@description Clase puramente abstracta
*/
package com.codemonkey;
public interface Servicio{

public abstract void mensaje();

}

ServicioImplA.java

/**
*
*@description Implementación de Servicio
*/
package com.codemonkey;
import static java.lang.System.out;

public class ServicioImplA implements Servicio {

@Override public void mensaje(){

out.println("Mensaje desde clase ServicioImplA");

}

}

ServicioImplB.java

/**
*
*@description Implementación de Servicio
*/
package com.codemonkey;
import static java.lang.System.out;

public class ServicioImplB implements Servicio {

@Override public void mensaje(){

out.println("Mensaje desde clase ServicioImplB");

}

}

Contenedor.java

/**
*@description Clase Contenedor
*
*/
package com.codemonkey;
public class Contenedor{

private Servicio servicio;

public Contenedor(Servicio servicio){

this.servicio=servicio;

}

public void mensaje(){

servicio.mensaje();

}

}

Main.java

/**
*
*@description Clase principal
*/
package com.codemonkey;
public class Main{

public static void main(String[] args){

Servicio servImplA = new ServicioImplA();

Servicio servImplB = new ServicioImplB();

Contenedor contenedor = new Contenedor(servImplA);

contenedor.mensaje(); //implementación: ServicioImplA

contenedor = new Contenedor(servImplB);

contenedor.mensaje(); //implementación: ServicioImplB

}

}

En conclusión, el contenedor (Contenedor.java) debería poder gestionar cualquier objeto, cualquier valor o argumento de cualquier método de cualquier clase.