3 Replies Latest reply on Feb 7, 2008 4:23 PM by Tony Herstell

    Seam Design Question

    Tony Herstell Master

      1/

      I have a number of resources
      say:
      Enum {A,B,C,D,E}

      I have "Hour Slots" when they are being used.

      I have users that can book the resource.

      I have created a Conversational Bean to select the resource(s) and now want a show the current bookings (for certain bookings this will be on same page using Ajax as only can book upto 14 days in advance)... so the user can book into slot(s) that are free (this gets more complicated when I have to auto-fit complicated bookings but we won't go there).

      My Proposed Solution:
      Create a Session Scoped bean (ResourceAllocation) with some members:
      AHourSlots
      BHourSlots
      CHourSlots
      etc.

      I chose Session as the site won't be hammered so I can afford a few database hits (and storage use) when new users hit the site to book a resource. (I can always move over to Application if need be later)... For now I somehow feel safer (VMS days) to throw away the resources when the session dies as any bugs in keeping it updated are localised to the max duration of a session ;)

      I want in my .xhtml page to just have access to the coped variables like:
      AHourSlots
      BHourSlots
      CHourSlots
      etc.
      And I believe that if I have them in ResourceAllocationImpl anotated with @Factory(scope=ScopeType.SESSION, value="AAllocation")
      then this would do the trick.

      Is this course likely to cause problems.
      (prefer not to have things in components.xml if I can help it as too disjoint from the code).

      2/

      As the page is ajaxified I end up with the booking all on one page, BUT I want to force the user to log in (or register) before the booking is saved and I cant see a way to do this unless I force them to go to a page which has a loggedIn guard (me thinks a confirmation page)... Is there a way programatically to do summat like this:

      public String saveTheBooking() {
      String nextNavigationPort = null;
      if (!loggedIn) {
      seam.core.nestToLogin();
      }
      if (loggedIn) {
      // Park the sucker under the users name
      em.persist(booking);
      nextNavigationPort = "home";
      return nextNavigationPort;
      } else {
      // Message the user to say refused to login so no-way-hozay
      ...
      }
      }

      This would be kinda useful for parking the booking part-through (as its quite complicated!)

        • 1. Re: Seam Design Question
          Tony Herstell Master

          Going back to 1/

          I need to initialise the "allocations" and this is generally done by a @Factory.

          This causes a stack Overflow...

          @SuppressWarnings("serial")
          @Scope(ScopeType.SESSION)
          @Name("allocations")
          public class Allocations implements Serializable {
          
           private List<Day> indoorArenaDays;
           private List<Day> dressageArenaDays;
           private List<Day> sjArenaDays;
          
           @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
           @Factory(scope=ScopeType.SESSION, value="allocations")
           public void init() {
          
           List<DaySlot> indoorArenaDaySlots = new ArrayList<DaySlot>();
           DaySlot daySlot = new DaySlot();
           daySlot.setBooked(true);
           daySlot.setBooker("Billy");
           daySlot.setBookingId(1l);
           daySlot.setReason(BookingReasonsKind.ONE_HOUR_PRIVATE);
           daySlot.setTitle("This is a test");
           indoorArenaDaySlots.add(daySlot);
          
           Day day = new Day();
           day.setDate(new GregorianCalendar());
           day.setDaySlots(indoorArenaDaySlots);
           indoorArenaDays = new ArrayList<Day>();
           this.indoorArenaDays.add(day);
           }
          
           @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
           public List<Day> getIndoorArenaDays() {
           //init();
           return indoorArenaDays;
           }
          
           @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
           public void setIndoorArenaDays(List<Day> indoorArenaDays) {
           this.indoorArenaDays = indoorArenaDays;
           }
          
           @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
           public List<Day> getDressageArenaDays() {
           return dressageArenaDays;
           }
          
           @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
           public void setDressageArenaDays(List<Day> dressageArenaDays) {
           this.dressageArenaDays = dressageArenaDays;
           }
          
           @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
           public List<Day> getSjArenaDays() {
           return sjArenaDays;
           }
          
           @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
           public void setSjArenaDays(List<Day> sjArenaDays) {
           this.sjArenaDays = sjArenaDays;
           }
          
          }
          


          This little class started as a POJO (used by my ResourceAllocationController) as it really didn't need to be a Seam Object (or so I though).... Anyhow now its a fully grown up Seam object.

          So... How do I get the Factory to work?

          Do I need and Interface and make this a body (impl)?



          This is the .xthml that calls it.... (and as such expects allocations to be set up - by the factory).

          <h:panelGrid class="left" id="day_slots_choices" width="20%">
           <rich:dataTable var="eachDayForIndoorArena" value="#{allocations.indoorArenaDays}"
           rendered="#{not empty allocations.indoorArenaDays}">
           <rich:column width="10%">
           <f:facet name="header">
           <h:outputText id="resource_date"
           value="#{messages.allocation_day}" />
           </f:facet>
           <div class="centre">
           <h:outputText value="#{eachDayForIndoorArena.date}">
           <s:convertDateTime type="date" dateStyle="full"/>
           </h:outputText>
           </div>
           </rich:column>
           </rich:dataTable>
          </h:panelGrid>
          


          If I hack the getXXX then the init will be called, but then it gets called every time.


          CONFUSED....

          • 2. Re: Seam Design Question
            Tony Herstell Master

            Having slept on this; I think that since it's a Seam Bean now; I can just call it from other beans... The bean can check if its been initialised already.. Really sub optimal solution.

            • 3. Re: Seam Design Question
              Tony Herstell Master

              So obvious really..

               @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
               @Create
               public void init() {