A continuación los pasos a seguir y cumplir con los requerimientos expuestos:
1. Ejecutamos el comando json add:
json add --class ~.model.Ejemplo
Este comando introducirá la anotación @RooJson en el tipo de destino especificado:
@RooJson public class Ejemplo { }
Y creara el siguiente archivo .aj donde están declarados todos los métodos que convertirán la entidad a json y viceversa:
package org.springroo.model; import flexjson.JSONDeserializer; import flexjson.JSONSerializer; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.springroo.model.Ejemplo; privileged aspect Ejemplo_Roo_Json { public String Ejemplo.toJson() { return new JSONSerializer().exclude("*.class").serialize(this); } public static Ejemplo Ejemplo.fromJsonToEjemplo(String json) { return new JSONDeserializer<Ejemplo>().use(null, Ejemplo.class).deserialize(json); } public static String Ejemplo.toJsonArray(Collection<Ejemplo> collection) { return new JSONSerializer().exclude("*.class").serialize(collection); } public static Collection<Ejemplo> Ejemplo.fromJsonArrayToEjemploes(String json) { return new JSONDeserializer<List<Ejemplo>>().use(null, ArrayList.class).use("values", Ejemplo.class).deserialize(json); } }
2. Crear un controllador donde se expondrán los servicios rest mediante el siguiente comando:
controller class --class ~.web.EjemploController --preferredMapping /restAPI/ejemplo
Esto creara la siguiente clase java:
package org.springroo.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springroo.model.Ejemplo; @RequestMapping("/restAPI/ejemplo") @Controller public class EjemploController { }
3. Ejecutamos el comando web mvc json add:
web mvc json add --jsonObject ~.model.Ejemplo --class ~.web.EjemploController
Este comando introduce la anotación @RooWebJson en el tipo de destino especificado.
package org.springroo.web; import org.springframework.roo.addon.web.mvc.controller.json.RooWebJson; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springroo.model.Ejemplo; @RequestMapping("/restAPI/ejemplo") @Controller @RooWebJson(jsonObject = Ejemplo.class) public class EjemploController { }
Creando este archivo .aj con los métodos crud restful:
// WARNING: DO NOT EDIT THIS FILE. THIS FILE IS MANAGED BY SPRING ROO. // You may push code into the target .java compilation unit if you wish to edit any member(s). package org.springroo.web; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springroo.model.Ejemplo; import org.springroo.services.EjemploService; import org.springroo.web.EjemploController; privileged aspect EjemploController_Roo_Controller_Json { @Autowired EjemploService EjemploController.EjemploService; @RequestMapping(value = "/{id}", headers = "Accept=application/json") @ResponseBody public ResponseEntityEjemploController.showJson(@PathVariable("id") Integer id) { Ejemplo Ejemplo = EjemploService.findEjemplo(id); HttpHeaders headers = new HttpHeaders(); headers.add("Content-Type", "application/json; charset=utf-8"); if (Ejemplo == null) { return new ResponseEntity (headers, HttpStatus.NOT_FOUND); } return new ResponseEntity (Ejemplo.toJson(), headers, HttpStatus.OK); } @RequestMapping(headers = "Accept=application/json") @ResponseBody public ResponseEntity EjemploController.listJson() { HttpHeaders headers = new HttpHeaders(); headers.add("Content-Type", "application/json; charset=utf-8"); List result = EjemploService.findAllEjemploes(); return new ResponseEntity (Ejemplo.toJsonArray(result), headers, HttpStatus.OK); } @RequestMapping(method = RequestMethod.POST, headers = "Accept=application/json") public ResponseEntity EjemploController.createFromJson(@RequestBody String json) { Ejemplo Ejemplo = Ejemplo.fromJsonToEjemplo(json); EjemploService.saveEjemplo(Ejemplo); HttpHeaders headers = new HttpHeaders(); headers.add("Content-Type", "application/json"); return new ResponseEntity (headers, HttpStatus.CREATED); } @RequestMapping(value = "/jsonArray", method = RequestMethod.POST, headers = "Accept=application/json") public ResponseEntity EjemploController.createFromJsonArray(@RequestBody String json) { for (Ejemplo Ejemplo: Ejemplo.fromJsonArrayToEjemploes(json)) { EjemploService.saveEjemplo(Ejemplo); } HttpHeaders headers = new HttpHeaders(); headers.add("Content-Type", "application/json"); return new ResponseEntity (headers, HttpStatus.CREATED); } @RequestMapping(method = RequestMethod.PUT, headers = "Accept=application/json") public ResponseEntity EjemploController.updateFromJson(@RequestBody String json) { HttpHeaders headers = new HttpHeaders(); headers.add("Content-Type", "application/json"); Ejemplo Ejemplo = Ejemplo.fromJsonToEjemplo(json); if (EjemploService.updateEjemplo(Ejemplo) == null) { return new ResponseEntity (headers, HttpStatus.NOT_FOUND); } return new ResponseEntity (headers, HttpStatus.OK); } @RequestMapping(value = "/jsonArray", method = RequestMethod.PUT, headers = "Accept=application/json") public ResponseEntity EjemploController.updateFromJsonArray(@RequestBody String json) { HttpHeaders headers = new HttpHeaders(); headers.add("Content-Type", "application/json"); for (Ejemplo Ejemplo: Ejemplo.fromJsonArrayToEjemploes(json)) { if (EjemploService.updateEjemplo(Ejemplo) == null) { return new ResponseEntity (headers, HttpStatus.NOT_FOUND); } } return new ResponseEntity (headers, HttpStatus.OK); } @RequestMapping(value = "/{id}", method = RequestMethod.DELETE, headers = "Accept=application/json") public ResponseEntity EjemploController.deleteFromJson(@PathVariable("id") Integer id) { Ejemplo Ejemplo = EjemploService.findEjemplo(id); HttpHeaders headers = new HttpHeaders(); headers.add("Content-Type", "application/json"); if (Ejemplo == null) { return new ResponseEntity (headers, HttpStatus.NOT_FOUND); } EjemploService.deleteEjemplo(Ejemplo); return new ResponseEntity (headers, HttpStatus.OK); } }
4. Asegurando nuestra aplicación mediante el siguiente comando:
spring security setup
Este comando creara el siguiente archivo de configuración: applicationContext-security.xml
Configuración que asegura nuestras urls de servicios rest pero sin redirigir a nuestro modulo de login:
<!-- HTTP security configurations -->
<http pattern="/restAPI/**" create-session="stateless" authentication-manager-ref="authenticationManager">
<intercept-url pattern="/restAPI/**" access="ROLE_ADMIN" />
<http-basic />
</http>
Y dejamos la configuración por defecto que nos genero spring roo:
<http auto-config="true" use-expressions="true" create-session="always">
<form-login login-processing-url="/resources/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t" />
<logout logout-url="/resources/j_spring_security_logout" />
<!-- Configure these elements to secure URIs in your application -->
<intercept-url pattern="/choices/**" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/member/**" access="isAuthenticated()" />
<intercept-url pattern="/resources/**" access="permitAll" />
<intercept-url pattern="/**" access="permitAll" />
</http>
5. Probamos nuestras configuraciones en el navegador y la salida de nuestros servicios rest:
Intentando acceder a un modulo seguro nos muestra el login form:
Intentado acceder a una url segura de nuestros servicios rest:
Consultando el registro con id = 1 de nuestra tabla ejemplo veamos la salida en nuestro navegador:
url: http://localhost:8080/appXXXXXXX/restAPI/ejemplo/1 muestra la siguiente salida:
{"id":1,"idejemplo":1,"t1":"","t11":"","t12":"","t13":"","t14":"","t15":"","t16":"","t17":"","t18":"","t2":"","t3":"","t4":"","t5":"","t6":"","t7":"","t8":"","text1":"WILLIAMS","text10":"","text11":"","text12":"","text13":"","text14":"","text15":"","text16":"","text17":"","text18":"","text19":"","text20":"","text21":"","text22":"","text23":"","text24":"","text25":"","text26":"","text27":"","text28":"","text29":"","text3":"","text30":"","text31":"","text32":"","text33":"","text34":"","text35":"","text36":"","text39":"","text4":"","text40":"","text41":"","text42":"","text43":"","text44":"","text45":"","text46":"","text47":"","text48":"","text49":null,"text5":"","text50":"","text52":"","text6":"","text7":"","text8":"","text9":""}
Consultando todos los registros:
url: http://localhost:8080/appNegocioIribarren/restAPI/ejemplo muestra la siguiente salida:
[{"id":2,"idejemplo":2,"t1":null,"t11":null,"t12":null,"t13":null,"t14":null,"t15":null,"t16":null,"t17":null,"t18":null,"t2":null,"t3":null,"t4":null,"t5":null,"t6":null,"t7":null,"t8":null,"text1":null,"text10":null,"text11":null,"text12":null,"text13":null,"text14":null,"text15":null,"text16":null,"text17":null,"text18":null,"text19":null,"text20":null,"text21":null,"text22":null,"text23":null,"text24":null,"text25":null,"text26":null,"text27":null,"text28":null,"text29":null,"text3":null,"text30":null,"text31":null,"text32":null,"text33":null,"text34":null,"text35":null,"text36":null,"text39":null,"text4":null,"text40":null,"text41":null,"text42":null,"text43":null,"text44":null,"text45":null,"text46":null,"text47":null,"text48":null,"text49":null,"text5":null,"text50":null,"text52":null,"text6":null,"text7":null,"text8":null,"text9":null},{"id":3,"idejemplo":3,"t1":"","t11":"","t12":"","t13":"","t14":"","t15":"","t16":"","t17":"","t18":"","t2":"","t3":"","t4":"","t5":"","t6":"","t7":"","t8":"","text1":"","text10":"","text11":"","text12":"","text13":"","text14":"","text15":"","text16":"","text17":"","text18":"","text19":"","text20":"","text21":"","text22":"","text23":"","text24":"","text25":"","text26":"","text27":"","text28":"","text29":"","text3":null,"text30":"","text31":"","text32":"","text33":"","text34":"","text35":"","text36":"","text39":"","text4":"","text40":"","text41":"","text42":"","text43":"","text44":"","text45":"","text46":"","text47":null,"text48":"","text49":null,"text5":"","text50":"","text52":null,"text6":"","text7":"","text8":"","text9":""},{"id":1,"idejemplo":1,"t1":"","t11":"","t12":"","t13":"","t14":"","t15":"","t16":"","t17":"","t18":"","t2":"","t3":"","t4":"","t5":"","t6":"","t7":"","t8":"","text1":"WILLIAMS","text10":"","text11":"","text12":"","text13":"","text14":"","text15":"","text16":"","text17":"","text18":"","text19":"","text20":"","text21":"","text22":"","text23":"","text24":"","text25":"","text26":"","text27":"","text28":"","text29":"","text3":"","text30":"","text31":"","text32":"","text33":"","text34":"","text35":"","text36":"","text39":"","text4":"","text40":"","text41":"","text42":"","text43":"","text44":"","text45":"","text46":"","text47":"","text48":"","text49":null,"text5":"","text50":"","text52":"","text6":"","text7":"","text8":"","text9":""}]
6.Agreamos la siguiente dependencia en nuestro archivo pom.xml la necesitaremos para comenzar a desarrollar nuestra aplicación cliente:
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.8</version>
</dependency>
7. Creando nuestra aplicación cliente mediante la api de jersey client, la explicaré mediante el mismo código:
package org.springroo.test; import java.io.IOException; import javax.naming.AuthenticationException; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.WebResource; import com.sun.star.lang.IllegalArgumentException; public class ClientJersey { public static void main(String[] args) throws IOException, AuthenticationException { Client client = Client.create(); try { String auth = new sun.misc.BASE64Encoder().encode("admin:admin" .getBytes()); WebResource webResource = client .resource("http://192.168.1.103:8080/appXXXXXX/restAPI/ejemplo"); ClientResponse response = webResource .header("Authorization", "Basic " + auth) .type("application/json").accept("application/json") .get(ClientResponse.class); int statusCode = response.getStatus(); if (statusCode == 401) { throw new AuthenticationException( "Invalid Username or Password"); } if (statusCode == 403) { throw new AuthenticationException("Usuario no autorizado"); } //Obtenemos el arreglo de objetos Ejemplo y lo recorremos para obtener el objeto de id = 1 JSONArray ja = new JSONArray(response.getEntity(String.class)); JSONObject joForUpdate = null; for (int i = 0; i < ja.length(); i++) { if (ja.getJSONObject(i).getInt("id") == 1) { joForUpdate = ja.getJSONObject(i); break; } } if (joForUpdate == null) throw new IllegalArgumentException("json object null"); System.out.println(joForUpdate.get("id")); joForUpdate.put("text1", "RIVAS"); // Luego de obtener el objeto de id = 1 realizamos la actualizacion de su atributo text1 response = webResource.header("Authorization", "Basic " + auth) .type("application/json").accept("application/json") .put(ClientResponse.class, joForUpdate.toString()); System.out.println("Estatus: " + response.getStatus()); } catch (JSONException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } finally { client.destroy(); } } }
8. Verificación de si el atributo text1 del registro con id = 1 cambio:
url: http://localhost:8080/appXXXXXX/restAPI/ejemplo
[{"id":2,"idejemplo":2,"t1":null,"t11":null,"t12":null,"t13":null,"t14":null,"t15":null,"t16":null,"t17":null,"t18":null,"t2":null,"t3":null,"t4":null,"t5":null,"t6":null,"t7":null,"t8":null,"text1":null,"text10":null,"text11":null,"text12":null,"text13":null,"text14":null,"text15":null,"text16":null,"text17":null,"text18":null,"text19":null,"text20":null,"text21":null,"text22":null,"text23":null,"text24":null,"text25":null,"text26":null,"text27":null,"text28":null,"text29":null,"text3":null,"text30":null,"text31":null,"text32":null,"text33":null,"text34":null,"text35":null,"text36":null,"text39":null,"text4":null,"text40":null,"text41":null,"text42":null,"text43":null,"text44":null,"text45":null,"text46":null,"text47":null,"text48":null,"text49":null,"text5":null,"text50":null,"text52":null,"text6":null,"text7":null,"text8":null,"text9":null},{"id":3,"idejemplo":3,"t1":"","t11":"","t12":"","t13":"","t14":"","t15":"","t16":"","t17":"","t18":"","t2":"","t3":"","t4":"","t5":"","t6":"","t7":"","t8":"","text1":null,"text10":"","text11":"","text12":"","text13":"","text14":"","text15":"","text16":"","text17":"","text18":"","text19":"","text20":"","text21":"","text22":"","text23":"","text24":"","text25":"","text26":"","text27":"","text28":"","text29":"","text3":null,"text30":"","text31":"","text32":"","text33":"","text34":"","text35":"","text36":"","text39":"","text4":"","text40":"","text41":"","text42":"","text43":"","text44":"","text45":"","text46":"","text47":null,"text48":"","text49":null,"text5":"","text50":"","text52":null,"text6":"","text7":"","text8":"","text9":""},{"id":1,"idejemplo":1,"t1":"","t11":"","t12":"","t13":"","t14":"","t15":"","t16":"","t17":"","t18":"","t2":"","t3":"","t4":"","t5":"","t6":"","t7":"","t8":"","text1":"RIVAS","text10":"","text11":"","text12":"","text13":"","text14":"","text15":"","text16":"","text17":"","text18":"","text19":"","text20":"","text21":"","text22":"","text23":"","text24":"","text25":"","text26":"","text27":"","text28":"","text29":"","text3":"","text30":"","text31":"","text32":"","text33":"","text34":"","text35":"","text36":"","text39":"","text4":"","text40":"","text41":"","text42":"","text43":"","text44":"","text45":"","text46":"","text47":"","text48":"","text49":null,"text5":"","text50":"","text52":"","text6":"","text7":"","text8":"","text9":""}]
Con esto hemos finalizado este corto pero muy educativo tutorial.