martedì 20 settembre 2011

jboss7: creare servizi rest - json

In jboss7 è semplice creare servizi rest!

Per iniziare basta dare un okkio al progetto di esempio distribuito come applicazione di esempio:
https://docs.jboss.org/author/display/AS7/Kitchensink+quickstart

L'unica difficoltà incontrata, nasce nel voler generare contenuti di tipo json, ovvero segnando i metodi con: @Produces("application/json")
Il problema riscontrato nasce nel mapping di relazioni di tipo @OneToMany, o meglio nell'escludere queste relazioni dal mapping del risultato (evitando l'errore:
org.codehaus.jackson.map.JsonMappingException: failed to lazily initialize a collection of role
date un okkio a questo post sul jbo7 forum: http://community.jboss.org/thread/169352 )

Facciamo un esempio pratico...
Immaginiamo di avere due entity Percorso, Punto (un percorso ha una relazione @OneToMany con i punti che lo costituiscono).

@Table(name = "percorsi")
@Entity
@XmlRootElement
public class Percorso implements Serializable {
private Long id;
private String nome;
        private List<Punto> punti;
.....

        @Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}

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

public String getNome() {
return nome;
}

public void setNome(String nome) {
this.nome = nome;
}

       @OneToMany(fetch = FetchType.LAZY, mappedBy = "percorso")
@XmlTransient
@JsonIgnore
public List<Punto> getPunti() {
if (punti == null)
this.punti = new ArrayList<Punto>();
return this.punti;
}

public void setPunti(List<Punto> punti) {
this.punti = punti;
}
}

@Table(name = "punti")
@Entity
@XmlRootElement
public class Punto implements Serializable {
private Long id;
private Percorso percorso;


       @Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}

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


        @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id_percorso")
@XmlTransient
@JsonIgnore
public Percorso getPercorso() {
return percorso;
}

public void setPercorso(Percorso percorso) {
this.percorso = percorso;
}
}

Immaginiamo di generare un servizio rest,

@Path("/v1/percorsi")
@RequestScoped
public class PercorsiREST {

.....

che permette di recuperare un percorso:

        // repository che gestisce il caricamento da db dei dati
        @Inject
PercorsiRepository percorsiRepository;

@GET
@Path("/{id:[0-9][0-9]*}")
@Produces("application/json")
public Percorso getPercorsoById(@PathParam("id") long id) {
Percorso percorso = percorsiRepository.fetch(id);
if (percorso == null) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
return percorso;
}

Saremo in grado di invocarlo all'indirizzo: http://localhost:8080/primetracks/rest/v1/percorsi/3 e restituirà una risposta json del tipo:
 
 [{"id":3,"nome":"04-08-2011"}]

Dato che la collezione di punti è stata annotata con @JsonIgnore i punti non verranno restituiti nel corpo della risposta.
Conoscendo l'id del percorso andremo ad invocare un secondo metodo, che fornisce i punti che lo compongono:

        @GET
@Path("/{id:[0-9][0-9]*}/punti")
@Produces("application/json")
public List<Punto> getPuntiByPercorsoId(@PathParam("id") long id) {
Percorso percorso = percorsiRepository.fetch(id);
if (percorso == null) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
return percorso.getPunti();
}
Che invocheremo all'indirizzo: http://localhost:8080/primetracks/rest/v1/percorsi/3/punti e restituirà una risposta json del tipo:

[{"id":130}, {"id":131}]

Do notare come l'annotazione @XmlTransient , svolge la stessa funzione nel caso si voglia mostrare il risultato in formato xml, usando @Produces("text/xml") al posto  di @Produces("application/json").

Ultima nota, per usare l'annotazione @JsonIgnore va aggiunto in maven:
                 <dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.6.3</version>
</dependency>
Inoltre per usare a runtime questa libreria, presente tra i moduli di jboss7, va aggiunto nel META-INF/MANIFEST.MF:
Dependencies: org.codehaus.jackson.jackson-core-asl


Provate!!



Nessun commento: