Fixed recursive relationship serialization.
This commit is contained in:
parent
0a019feeba
commit
4aa20221f0
@ -3,7 +3,7 @@ database:
|
|||||||
driverClass: org.h2.Driver
|
driverClass: org.h2.Driver
|
||||||
|
|
||||||
# the JDBC URL
|
# the JDBC URL
|
||||||
url: jdbc:h2:./sampledatabase.db
|
url: jdbc:h2:file:./sampledatabase.db
|
||||||
|
|
||||||
# any properties specific to your JDBC driver:
|
# any properties specific to your JDBC driver:
|
||||||
properties:
|
properties:
|
||||||
@ -17,4 +17,4 @@ server:
|
|||||||
- type: console
|
- type: console
|
||||||
queueSize: 2048
|
queueSize: 2048
|
||||||
|
|
||||||
adminPassword: "testPassword"
|
adminPassword: "testPassword"
|
||||||
|
@ -11,7 +11,6 @@ import java.io.Serializable;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ToString(callSuper = true)
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "OBSERVATION")
|
@Table(name = "OBSERVATION")
|
||||||
@Data
|
@Data
|
||||||
@ -27,13 +26,13 @@ public class Observation implements Serializable {
|
|||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
private long id;
|
private long id;
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
@JoinColumn(name="site_id", nullable=false)
|
@JoinColumn(name="site_id", nullable=false)
|
||||||
|
@EqualsAndHashCode.Exclude
|
||||||
private Site site;
|
private Site site;
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
@ManyToMany(mappedBy = "observations")
|
@ManyToMany(mappedBy = "observations")
|
||||||
|
@EqualsAndHashCode.Exclude
|
||||||
private Set<Tutor> tutors;
|
private Set<Tutor> tutors;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
package uk.co.neviyn.Observations.core;
|
package uk.co.neviyn.Observations.core;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@EqualsAndHashCode
|
|
||||||
@ToString
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "SITE")
|
@Table(name = "SITE")
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@Builder
|
@Builder
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
|
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
|
||||||
public class Site implements Serializable {
|
public class Site implements Serializable {
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -27,12 +28,11 @@ public class Site implements Serializable {
|
|||||||
@JsonProperty
|
@JsonProperty
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
@OneToMany(mappedBy="site")
|
@OneToMany(mappedBy="site")
|
||||||
|
@EqualsAndHashCode.Exclude
|
||||||
private Set<Tutor> tutors;
|
private Set<Tutor> tutors;
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
@OneToMany(mappedBy = "site")
|
@OneToMany(mappedBy = "site")
|
||||||
|
@EqualsAndHashCode.Exclude
|
||||||
private Set<Observation> observations;
|
private Set<Observation> observations;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,21 @@
|
|||||||
package uk.co.neviyn.Observations.core;
|
package uk.co.neviyn.Observations.core;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ToString
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "TUTOR")
|
@Table(name = "TUTOR")
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Builder
|
@Builder
|
||||||
|
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
|
||||||
public class Tutor implements Serializable {
|
public class Tutor implements Serializable {
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -26,17 +28,17 @@ public class Tutor implements Serializable {
|
|||||||
@JsonProperty
|
@JsonProperty
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
@JoinColumn(name="site_id", nullable=false)
|
@JoinColumn(name="site_id", nullable=false)
|
||||||
|
@EqualsAndHashCode.Exclude
|
||||||
private Site site;
|
private Site site;
|
||||||
|
|
||||||
@JsonProperty
|
|
||||||
@ManyToMany
|
@ManyToMany
|
||||||
@JoinTable(
|
@JoinTable(
|
||||||
name = "TUTOR_OBSERVATION",
|
name = "TUTOR_OBSERVATION",
|
||||||
joinColumns = { @JoinColumn(name = "tutor_id")},
|
joinColumns = { @JoinColumn(name = "tutor_id")},
|
||||||
inverseJoinColumns = { @JoinColumn(name = "observation_id")}
|
inverseJoinColumns = { @JoinColumn(name = "observation_id")}
|
||||||
)
|
)
|
||||||
|
@EqualsAndHashCode.Exclude
|
||||||
private Set<Observation> observations;
|
private Set<Observation> observations;
|
||||||
}
|
}
|
||||||
|
@ -37,26 +37,21 @@ public class ObservationResource {
|
|||||||
|
|
||||||
@POST
|
@POST
|
||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
public long add(@NotNull @Valid NewObservation newObservation){
|
public long add(@NotNull @Valid NewObservation newObservation) {
|
||||||
final DateTime submissionDate = LocalDate.now().toDateTimeAtStartOfDay();
|
final DateTime submissionDate = LocalDate.now().toDateTimeAtStartOfDay();
|
||||||
Set<Tutor> tutors = new HashSet<>();
|
Set<Tutor> tutors = new HashSet<>();
|
||||||
for(long l: newObservation.getTutorIds()){
|
for (long l : newObservation.getTutorIds()) {
|
||||||
tutors.add(tutorDao.get(l));
|
tutors.add(tutorDao.get(l));
|
||||||
}
|
}
|
||||||
final Site site = siteDao.get(newObservation.getSiteId());
|
final Site site = siteDao.get(newObservation.getSiteId());
|
||||||
Observation observation = Observation.builder()
|
Observation observation = Observation.builder().site(site).tutors(tutors).observed(newObservation.getObserved())
|
||||||
.site(site)
|
.type(TrainingType.valueOf(newObservation.getType())).monitoring(newObservation.getMonitoring())
|
||||||
.tutors(tutors)
|
.control(newObservation.getControl()).conservatism(newObservation.getConservatism())
|
||||||
.observed(newObservation.getObserved())
|
.teamwork(newObservation.getTeamwork()).knowledge(newObservation.getKnowledge())
|
||||||
.type(TrainingType.valueOf(newObservation.getType()))
|
.observations(newObservation.getRawData()).date(submissionDate).build();
|
||||||
.monitoring(newObservation.getMonitoring())
|
for (Tutor t : tutors) {
|
||||||
.control(newObservation.getControl())
|
t.getObservations().add(observation);
|
||||||
.conservatism(newObservation.getConservatism())
|
}
|
||||||
.teamwork(newObservation.getTeamwork())
|
|
||||||
.knowledge(newObservation.getKnowledge())
|
|
||||||
.observations(newObservation.getRawData())
|
|
||||||
.date(submissionDate)
|
|
||||||
.build();
|
|
||||||
observation = dao.persist(observation);
|
observation = dao.persist(observation);
|
||||||
log.info("Created observation with ID " + observation.getId() + " at " + DateTime.now().toString());
|
log.info("Created observation with ID " + observation.getId() + " at " + DateTime.now().toString());
|
||||||
return observation.getId();
|
return observation.getId();
|
||||||
@ -64,23 +59,27 @@ public class ObservationResource {
|
|||||||
|
|
||||||
@Path("/average/all")
|
@Path("/average/all")
|
||||||
@GET
|
@GET
|
||||||
public List<AverageStats> averageObservationScores(){
|
@UnitOfWork
|
||||||
|
public List<AverageStats> averageObservationScores() {
|
||||||
return dao.averageStatsForAll();
|
return dao.averageStatsForAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("/average/all/chartjs")
|
@Path("/average/all/chartjs")
|
||||||
@GET
|
@GET
|
||||||
public AverageStatsChartJs averageStatsChartJs(){
|
public AverageStatsChartJs averageStatsChartJs() {
|
||||||
return new AverageStatsChartJs(averageObservationScores());
|
return new AverageStatsChartJs(averageObservationScores());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("/average/{id}")
|
@Path("/average/{id}")
|
||||||
|
@GET
|
||||||
|
@UnitOfWork
|
||||||
public List<AverageStats> averageObservationScoresForSite(@PathParam("id") long siteId) {
|
public List<AverageStats> averageObservationScoresForSite(@PathParam("id") long siteId) {
|
||||||
Site site = siteDao.get(siteId);
|
Site site = siteDao.get(siteId);
|
||||||
return dao.averageStatsForSite(site);
|
return dao.averageStatsForSite(site);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("/average/{id}/chartjs")
|
@Path("/average/{id}/chartjs")
|
||||||
|
@GET
|
||||||
public AverageStatsChartJs averageObservationScoresForSiteChartJs(@PathParam("id") long siteId) {
|
public AverageStatsChartJs averageObservationScoresForSiteChartJs(@PathParam("id") long siteId) {
|
||||||
return new AverageStatsChartJs(averageObservationScoresForSite(siteId));
|
return new AverageStatsChartJs(averageObservationScoresForSite(siteId));
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,12 @@ import io.dropwizard.hibernate.UnitOfWork;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import uk.co.neviyn.Observations.api.SelectOption;
|
import uk.co.neviyn.Observations.api.SelectOption;
|
||||||
import uk.co.neviyn.Observations.core.Site;
|
import uk.co.neviyn.Observations.core.Site;
|
||||||
import uk.co.neviyn.Observations.core.Tutor;
|
|
||||||
import uk.co.neviyn.Observations.core.User;
|
import uk.co.neviyn.Observations.core.User;
|
||||||
import uk.co.neviyn.Observations.dao.SiteDao;
|
import uk.co.neviyn.Observations.dao.SiteDao;
|
||||||
|
|
||||||
import javax.ws.rs.*;
|
import javax.ws.rs.*;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@ -38,7 +36,7 @@ public class SiteResource {
|
|||||||
@Path("/{id}/tutors")
|
@Path("/{id}/tutors")
|
||||||
@GET
|
@GET
|
||||||
@UnitOfWork
|
@UnitOfWork
|
||||||
public Set<Tutor> getSiteTutors(@PathParam("id") long id){
|
public List<SelectOption<Long>> getSiteTutors(@PathParam("id") long id) {
|
||||||
return dao.get(id).getTutors();
|
return dao.get(id).getTutors().stream().map(x -> new SelectOption<>(x.getName(), x.getId())).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import lombok.AllArgsConstructor;
|
|||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import uk.co.neviyn.Observations.core.Observation;
|
||||||
import uk.co.neviyn.Observations.core.Site;
|
import uk.co.neviyn.Observations.core.Site;
|
||||||
import uk.co.neviyn.Observations.core.Tutor;
|
import uk.co.neviyn.Observations.core.Tutor;
|
||||||
import uk.co.neviyn.Observations.core.User;
|
import uk.co.neviyn.Observations.core.User;
|
||||||
@ -17,6 +18,7 @@ import javax.ws.rs.*;
|
|||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@ -31,6 +33,7 @@ public class TutorResource {
|
|||||||
public Tutor add(@Auth User user, NewTutor newTutor) {
|
public Tutor add(@Auth User user, NewTutor newTutor) {
|
||||||
final Site site = siteDao.get(newTutor.siteId);
|
final Site site = siteDao.get(newTutor.siteId);
|
||||||
final Tutor tutor = Tutor.builder().name(newTutor.name).site(site).build();
|
final Tutor tutor = Tutor.builder().name(newTutor.name).site(site).build();
|
||||||
|
site.getTutors().add(tutor);
|
||||||
return dao.persist(tutor);
|
return dao.persist(tutor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +47,13 @@ public class TutorResource {
|
|||||||
throw new WebApplicationException("No tutors found!", Response.Status.NOT_FOUND);
|
throw new WebApplicationException("No tutors found!", Response.Status.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Path("/{id}/observations")
|
||||||
|
@GET
|
||||||
|
@UnitOfWork
|
||||||
|
public Set<Observation> getSiteTutors(@PathParam("id") long id) {
|
||||||
|
return dao.get(id).getObservations();
|
||||||
|
}
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
static class NewTutor {
|
static class NewTutor {
|
||||||
|
@ -15,6 +15,7 @@ import uk.co.neviyn.Observations.dao.TutorDao;
|
|||||||
import javax.ws.rs.client.Entity;
|
import javax.ws.rs.client.Entity;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
@ -40,7 +41,7 @@ public class ObservationResourceTest {
|
|||||||
@Test
|
@Test
|
||||||
public void add() {
|
public void add() {
|
||||||
final Site testSite = Site.builder().id(1).name("Test Site").build();
|
final Site testSite = Site.builder().id(1).name("Test Site").build();
|
||||||
final List<Tutor> tutors = Arrays.asList(Tutor.builder().id(1).name("Mr A").build(), Tutor.builder().id(2).name("Mr B").build());
|
final List<Tutor> tutors = Arrays.asList(Tutor.builder().id(1).name("Mr A").observations(new HashSet<>()).build(), Tutor.builder().id(2).name("Mr B").observations(new HashSet<>()).build());
|
||||||
when(siteDao.get(1)).thenReturn(testSite);
|
when(siteDao.get(1)).thenReturn(testSite);
|
||||||
when(tutorDao.get(1)).thenReturn(tutors.get(0));
|
when(tutorDao.get(1)).thenReturn(tutors.get(0));
|
||||||
when(tutorDao.get(2)).thenReturn(tutors.get(1));
|
when(tutorDao.get(2)).thenReturn(tutors.get(1));
|
||||||
|
@ -50,7 +50,7 @@ public class SiteResourceTest {
|
|||||||
@Test
|
@Test
|
||||||
public void add() {
|
public void add() {
|
||||||
resources.target("/site").request().header("Authorization", httpAuth).post(Entity.json("New Site"));
|
resources.target("/site").request().header("Authorization", httpAuth).post(Entity.json("New Site"));
|
||||||
verify(dao, times(1)).persist(Site.builder().name("New Site").build());
|
verify(dao, times(1)).persist(Site.builder().name("New Site").tutors(new HashSet<>()).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -66,9 +66,9 @@ public class SiteResourceTest {
|
|||||||
public void getSiteTutors() {
|
public void getSiteTutors() {
|
||||||
Set<Tutor> tutors = new HashSet<>(Arrays.asList(Tutor.builder().id(1).name("Test 1").build(), Tutor.builder().id(2).name("Test 2").build()));
|
Set<Tutor> tutors = new HashSet<>(Arrays.asList(Tutor.builder().id(1).name("Test 1").build(), Tutor.builder().id(2).name("Test 2").build()));
|
||||||
when(dao.get(1)).thenReturn(Site.builder().id(1).name("Site").tutors(tutors).build());
|
when(dao.get(1)).thenReturn(Site.builder().id(1).name("Site").tutors(tutors).build());
|
||||||
Set<Tutor> result = resources.target("/site/1/tutors").request().get(new GenericType<Set<Tutor>>() {
|
List<SelectOption<Long>> result = resources.target("/site/1/tutors").request().get(new GenericType<List<SelectOption<Long>>>() {
|
||||||
});
|
});
|
||||||
assertNotNull(result);
|
assertNotNull(result);
|
||||||
assertEquals(tutors, result);
|
assertEquals(2, result.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,6 +17,7 @@ import uk.co.neviyn.Observations.dao.TutorDao;
|
|||||||
import javax.ws.rs.client.Entity;
|
import javax.ws.rs.client.Entity;
|
||||||
import javax.ws.rs.core.GenericType;
|
import javax.ws.rs.core.GenericType;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
@ -48,7 +49,7 @@ public class TutorResourceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void add() {
|
public void add() {
|
||||||
final Site testSite = Site.builder().id(1).name("Test Site").build();
|
final Site testSite = Site.builder().id(1).name("Test Site").tutors(new HashSet<>()).build();
|
||||||
when(siteDao.get(1)).thenReturn(testSite);
|
when(siteDao.get(1)).thenReturn(testSite);
|
||||||
resources.target("/tutor").request().header("Authorization", httpAuth).post(Entity.json(new TutorResource.NewTutor(1, "Mr X")));
|
resources.target("/tutor").request().header("Authorization", httpAuth).post(Entity.json(new TutorResource.NewTutor(1, "Mr X")));
|
||||||
verify(dao, times(1)).persist(Tutor.builder().name("Mr X").site(testSite).build());
|
verify(dao, times(1)).persist(Tutor.builder().name("Mr X").site(testSite).build());
|
||||||
|
Loading…
Reference in New Issue
Block a user