3

I have what I think is a fairly simple problem, but after many hours of searching can find the solution, and I'm relatively new to Spring so please excuse any incorrect terminology or obvious errors.

I have an event object, which has a one-to-many relationship to a booking object as shown below

Event:

@Entity
public class Event {

   @Id
   @GeneratedValue(strategy=GenerationType.AUTO)
   private Long eventId;
   private Date start;
   private Date end;
   private String title;

   @OneToMany(mappedBy="event")
   private Set<Booking> Bookings;

   protected Event() {
       // for JPA
   }
   // Getters and setters omitted for brevity
}

Booking:

@Entity
public class Booking {  

   @Id
   @GeneratedValue(strategy=GenerationType.AUTO)
   private Long bookingId;
   private String title;
   private String contact;

   @ManyToOne
   @JoinColumn(name="event_id", nullable=false)
   private Event event; 

   public DiveBooking() {
      // for JPA
   }
   // Getters and setters omitted for brevity
}

EventRepository:

public interface DiveEventRepository extends JpaRepository<Event, Long> {

List<Event> findByStartBetweenOrEndBetween(
        @Param("start") Date startStartTime,
        @Param("end") Date startEndTime,
        @Param("start") Date endStartTime,
        @Param("end") Date endEndTime);
}

BookingRepository

public interface BookingRepository extends JpaRepository<Booking, Long>{

}

These expose the endpoints:

/rest/events /rest/bookings

An instance of an event as:

/rest/events/1

with its bookings:

/rest/events/1/bookings

What I'm trying to achieve, is to create a new booking and have it associated with an event. My data model has event_id as a required field (as a booking is meaningless without an event), and every fibre in my being says that I should be able to post a new booking object to /rest/events/1/bookings and have it create a new booking object that is associated with event with id 1. However, whenever I try and post to that URI, I get the message:

Failed to load resource: the server responded with a status of 405 (Method Not Allowed)

When inspecting the headers for the endpoint /rest/events/1/bookings I can see that post is allowed:

Access-Control-Allow-Methods:POST, GET, OPTIONS, DELETE

So now I'm completely confused and at a loss. It feels like I should be able to create a booking this way, and I really don't want to go down the route of having to create an orphaned booking then associate it with the event as it would break my data model (having to make event_id null in booking), and there is no way to do those to operations inside a transaction (is there?). I've tried doing similar operations on other collections in my model, and they have post denied too, so I'm guessing it's something to do with my spring data rest configuration, but I don't know what.

Thanks in advance for any help or pointers on this.

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
Drew
  • 464
  • 1
  • 5
  • 18
  • A similiar question to yours .. http://stackoverflow.com/questions/25311978/posting-a-onetomany-sub-resource-association-in-spring-data-rest – ArunM May 31 '15 at 12:17

3 Answers3

2

Post your new booking to: /rest/bookings

{
  "title": "my booking title",
  "contact": "my contact",
  "event": "http:localhost:8080/rest/events/1"
}

As others have already answered, you CAN create a booking and then associate it to an event by doing a PUT (text/uri-list) to /rest/events/1/bookings, but I think the above method is much more sensible.

Yan Foto
  • 10,850
  • 6
  • 57
  • 88
gyoder
  • 4,530
  • 5
  • 29
  • 37
  • Thank you very much for the "text/uri-list" tip. That works for me, althogh the current Spring Documentation sais one should send Content-Type: "application/json". But it doesn't specify any JSON format to send. – Robert Jan 08 '17 at 13:57
1

/rest/events/1/bookings is an association resource. It can only handle URIs.

If you want to create a new Booking then it's somewhat logical to post to /rest/bookings. The event field should contain the URI of the associated event, e.g. /rest/events/1.

Btw: Access-Control-Allow-Methods is not necessarily an indication of what methods the API supports. It's only relevant for cross domain browser requests and it's value is most likely the same for every URL.

a better oliver
  • 26,330
  • 2
  • 58
  • 66
  • Thanks, I think I'd tried everything but this in posting to /rest/bookings including putting an event object in the event field and putting the event uri in the _links on booking. – Drew Jun 03 '15 at 19:48
0

This is not a problem with your spring rest configuration as follows from the following thread. My understanding is the way you are trying to do is not supported by Spring rest

As given here, You have to use the following to update a resource which means that you have to update your model.

curl -v -X PUT -H "Content-Type: text/uri-list" -d "http://localhost:8080/events/1" http://localhost:8080/bookings/1/event
Community
  • 1
  • 1
ArunM
  • 2,274
  • 3
  • 25
  • 47
  • I think the poster wants to create a new booking and have it linked to an existing event in a single transaction. Using the update resource mechanism requires the booking to be created first, and then linked, which is two transactions. – Jason May 31 '15 at 18:27
  • From the discussions on the answers that I have linked to, my understanding it is not possible to do what is being asked in the question – ArunM Jun 01 '15 at 05:37
  • I have already seen the thread that's mentioned, and it didn't really answer what I'm trying to do. As Jay commented, I want to be able to do this in one transaction as all the information is available (the referenced id). Also, there is the question of why I get the message that the POST isn't allowed, despite the response headers saying that POST is allowed. – Drew Jun 01 '15 at 07:17
  • As far as my understanding is, You are trying to do something which is not supported. As far as the POST is concerned, I think this is something that needs to be changed in the framework which they havent got to doing – ArunM Jun 01 '15 at 07:26