I've started working on a REST API using Spring. I'm using the tutorial project gs-accessing-data-rest-initial, which is easy to dowload via Spring Tool Suite, in order to get some stuff working as soon as possible.
I've exposed two related entities (aplicacion and registros_app), using PagingAndSortingRepository and annotated both with @RepositoryRestResource, which enables me to expose entities correctly. The result I'm getting when I query on aplicacion is
**GET http://localhost:8090/aplicacion**
{
"_links" : {
"self" : {
"href" : "http://localhost:8090/aplicacion/{?page,size,sort}",
"templated" : true
}
},
"_embedded" : {
"aplicacion" : [ {
"nombre" : "app1",
"_links" : {
"self" : {
"href" : "http://localhost:8090/aplicacion/2"
},
"registrosApp" : {
"href" : "http://localhost:8090/aplicacion/2/registrosApp"
},
"tipoRegistrosApp" : {
"href" : "http://localhost:8090/aplicacion/2/tipoRegistrosApp"
}
}
}, {
"nombre" : "app2",
"_links" : {
"self" : {
"href" : "http://localhost:8090/aplicacion/1"
},
"registrosApp" : {
"href" : "http://localhost:8090/aplicacion/1/registrosApp"
},
"tipoRegistrosApp" : {
"href" : "http://localhost:8090/aplicacion/1/tipoRegistrosApp"
}
}
} ]
},
"page" : {
"size" : 20,
"totalElements" : 2,
"totalPages" : 1,
"number" : 0
}
}
Which is exactly what I've expected to obtain. So, I was expecting to get the same when I navigate to registrosApp, in terms of pagination; however, when I perform a get on any registrosApp link, what I retrieve from the query is
**GET http://localhost:8090/aplicacion/2/registrosApp**
{
"_embedded" : {
"registrosapp" : [ {
"datos" : "{\"FechaInicio\":\"2014-09-16 18:08:44\",\"UsoMemoria\":\"UsedMemory:3 FreeMemory:491 Total Memory:495 Max Memory:989 \",\"InfoPool\":\"Active: 2\"}",
"fecha_hora" : "2014-09-17T14:04:07.000+0000",
"codTipoRegistro" : 1,
"_links" : {
"self" : {
"href" : "http://localhost:8090/registrosApp/605"
},
"aplicacion" : {
"href" : "http://localhost:8090/registrosApp/605/aplicacion"
}
}
},{
"datos" : "{\"FechaInicio\":\"2014-09-16 18:08:44\",\"UsoMemoria\":\"UsedMemory:3 FreeMemory:491 Total Memory:495 Max Memory:989 \",\"InfoPool\":\"Active: 2\"}",
"fecha_hora" : "2014-09-17T14:04:07.000+0000",
"codTipoRegistro" : 1,
"_links" : {
"self" : {
"href" : "http://localhost:8090/registrosApp/667"
},
"aplicacion" : {
"href" : "http://localhost:8090/registrosApp/667/aplicacion"
}
}
} ]
}
}
Which is not actually paginated. I need to get a paginated json when I navigate across links because registrosApp table grows very quickly. ¿What can I do about it?
Here is the code for my registrosApp and aplicacion repository
@RepositoryRestResource(collectionResourceRel = "registrosapp", path = "registrosApp")
public interface RegistrosAppRepository extends PagingAndSortingRepository<RegistrosApp, Long> {
}
@RepositoryRestResource(collectionResourceRel = "aplicacion", path = "aplicacion")
public interface AplicacionRepository extends PagingAndSortingRepository<Aplicacion, Long> {
//List<Person> findByLastName(@Param("name") String name);
}
And those are the entities I've defined
@Entity
@Table(name = "registros_app")
public class RegistrosApp {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long idRegistrosApp;
private String datos;
private Date fecha_hora;
private long codTipoRegistro;
public long getCodTipoRegistro() {
return codTipoRegistro;
}
public void setCodTipoRegistro(long codTipoRegistro) {
this.codTipoRegistro = codTipoRegistro;
}
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "idAplicacion", nullable = false, insertable = false, updatable = false)
Aplicacion aplicacion;
// private long idAplicacion;
/*
* public long getRegistros_app() { return idAplicacion; }
*
* public void setRegistros_app(long registros_app) { this.idAplicacion =
* registros_app; }
*/
public String getDatos() {
return datos;
}
public void setDatos(String datos) {
this.datos = datos;
}
public Date getFecha_hora() {
return fecha_hora;
}
public void setFecha_hora(Date fecha_hora) {
this.fecha_hora = fecha_hora;
}
}
@Entity
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Aplicacion {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long aplicacionId;
private String nombre;
//relaciones uno a varios
//relacion con la tabla registros_app
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "idAplicacion", nullable = false)
private Set<RegistrosApp> registrosApp = null;
//relacion con la tabla tipo_registro_app
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "idApp", nullable = false)
private Set<TipoRegistrosApp> tipoRegistrosApp = null;
public Set<TipoRegistrosApp> getTipoRegistrosApp() {
return tipoRegistrosApp;
}
public void setTipoRegistrosApp(Set<TipoRegistrosApp> tipoRegistrosApp) {
this.tipoRegistrosApp = tipoRegistrosApp;
}
@JsonProperty
public Set<RegistrosApp> getRegistrosApp() {
return registrosApp;
}
/**
* Sets list of <code>Address</code>es.
*/
public void setRegistrosApp(Set<RegistrosApp> rapps) {
this.registrosApp= rapps;
}
@JsonProperty
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
}
You can notice that I have a @onetomany annotation between aplicacion and registrosapp in my entities.
TL;DR When I query directly on registrosapp I get a paginated result as I expect. The problem here is when I navigate between related entities, I'm not getting the pagination information I need. ¿What can I do in order to get pagination when I navigate across entities? Any help with this will be truly appreciated. Thanks in advance.
I will answer myself in order to get this question useful for someone else who is struggling with this problem. This answer is closely related to - Spring Data Rest Pageable Child Collection -
What I've done is to set a method within RegistrosAppRepository, so it stays like this
@RepositoryRestResource(collectionResourceRel = "registrosapp", path = "registrosApp")
public interface RegistrosAppRepository extends PagingAndSortingRepository<RegistrosApp, Long> {
@RestResource(path = "byAplicacion", rel = "byAplicacion")
public Page<RegistrosApp> findByAplicacion(@Param("aplicacion_id") Aplicacion aplicacion, Pageable p);
}
Then I hide the link to registrosApp which appears in aplicacion, by setting the annotation @RestResource(exported=false)
before the Set of registrosApp. So the aplicacion entity stays like this
@Entity
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Aplicacion {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long aplicacionId;
private String nombre;
//relaciones uno a varios
//relacion con la tabla registros_app
@RestResource(exported=false)
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "idAplicacion", nullable = false)
private Set<RegistrosApp> registrosApp = null;
//relacion con la tabla tipo_registro_app
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "idApp", nullable = false)
private Set<TipoRegistrosApp> tipoRegistrosApp = null;
public Set<TipoRegistrosApp> getTipoRegistrosApp() {
return tipoRegistrosApp;
}
public void setTipoRegistrosApp(Set<TipoRegistrosApp> tipoRegistrosApp) {
this.tipoRegistrosApp = tipoRegistrosApp;
}
@JsonProperty
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
}
finally, I'm able to navigate between those entities this way:
**GET http://localhost:8090/registrosApp/search/byAplicacion?aplicacion_id=2&page=1&size=1**
{
"_links" : {
"next" : {
"href" : "http://localhost:8090/registrosApp/search/byAplicacion?aplicacion_id=2&page=2&size=1"
},
"prev" : {
"href" : "http://localhost:8090/registrosApp/search/byAplicacion?aplicacion_id=2&page=0&size=1"
},
"self" : {
"href" : "http://localhost:8090/registrosApp/search/byAplicacion?aplicacion_id=2&page=1&size=1{&sort}",
"templated" : true
}
},
"_embedded" : {
"registrosapp" : [ {
"datos" : "{\"FechaInicio\":\"2014-09-16 18:08:44\",\"UsoMemoria\":\"UsedMemory:2 FreeMemory:492 Total Memory:495 Max Memory:989 \",\"InfoPool\":\"Active: 2\"}",
"fecha_hora" : "2014-09-17T14:04:07.000+0000",
"codTipoRegistro" : 1,
"_links" : {
"self" : {
"href" : "http://localhost:8090/registrosApp/593"
},
"aplicacion" : {
"href" : "http://localhost:8090/registrosApp/593/aplicacion"
}
}
} ]
},
"page" : {
"size" : 1,
"totalElements" : 56,
"totalPages" : 56,
"number" : 1
}
}
and the link in aplicacion doesn't show the registrosApp link whithin the json:
**GET http://localhost:8090/aplicacion**
{
"_links" : {
"self" : {
"href" : "http://localhost:8090/aplicacion{?page,size,sort}",
"templated" : true
}
},
"_embedded" : {
"aplicacion" : [ {
"nombre" : "app1",
"_links" : {
"self" : {
"href" : "http://localhost:8090/aplicacion/2"
},
"tipoRegistrosApp" : {
"href" : "http://localhost:8090/aplicacion/2/tipoRegistrosApp"
},
"aplicacion" : {
"href" : "http://localhost:8090/aplicacion/2/aplicacion"
}
}
}, {
"nombre" : "app2",
"_links" : {
"self" : {
"href" : "http://localhost:8090/aplicacion/1"
},
"tipoRegistrosApp" : {
"href" : "http://localhost:8090/aplicacion/1/tipoRegistrosApp"
},
"aplicacion" : {
"href" : "http://localhost:8090/aplicacion/1/aplicacion"
}
}
} ]
},
"page" : {
"size" : 20,
"totalElements" : 2,
"totalPages" : 1,
"number" : 0
}
}