4 Replies Latest reply on May 30, 2007 3:04 PM by Gavin King

    Seam Application Framework - The conversation ended, timed o

    Tomas Mika Newbie

      Hi,
      as I am quiet new in JBoss Seam and trying to understand the Seam's conversations, I probably havent catched the conversaions idea fully.

      When I try to update some record using EntityHome object (Car), I get this message:
      The conversation ended, timed out or was processing another request

      But it updates the database model anyway.. When the carList.xhtml page is redisplayed, the chages are included.

      If I try to create the new one Car in the database, sometimes I get the same message during the filling the Car form, even I don't press any "Create" button.

      I have very simple user-detail application. The carList.xhtml displays the list of available cars. The user can select one of the cars listed and the car detail is displayed. After that the user can press "Edit" button to display the edit car form. The user can also select "New car" from the car list page.

      Can you anyone please help me with the strange behaviour? Where have I made the mistake? Thanks

      here is the simpified code (the relevant part):

      User Entity Bean

      @Entity
      @Name("user")
      @Table(name = "user_table", uniqueConstraints = @UniqueConstraint(columnNames = "username"))
      @Scope(ScopeType.CONVERSATION)
      @org.jboss.seam.annotations.Role(name = "currentUser", scope = ScopeType.SESSION)
      @NamedQueries(@NamedQuery(name = "User.findAll", query = "SELECT u FROM User u ORDER BY u.username"))
      public class User implements java.io.Serializable {
      
       private static final long serialVersionUID = 4768507156434434655L;
      
       @Id
       @GeneratedValue
       @Column(name = "id", unique = true, nullable = false)
       private Integer id;
      
       @NotNull
       @Length(min = 5, max = 15)
       @Column(name = "username", unique = true, nullable = false)
       private String username;
      
       @NotNull
       @Length(min = 5, max = 15)
       @Column(name = "password", nullable = false)
       private String password;
      
       @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user", targetEntity=Car.class)
       private List<Car> cars = new ArrayList<Car>();
      
      
       public User() {
       }
      
       // ////////////////////////////////
       // getters and setters
       // ////////////////////////////////
      
       public String getUsername() {
       return this.username;
       }
      
       public void setUsername(String username) {
       this.username = username;
       }
      
       public String getPassword() {
       return this.password;
       }
      
       public void setPassword(String password) {
       this.password = password;
       }
      
       public List<Car> getCars() {
       return this.cars;
       }
      
       public void setCars(List<Car> cars) {
       this.cars = cars;
       }
      
       public Integer getId() {
       return id;
       }
      
       public void setId(Integer id) {
       this.id = id;
       }
      
      }
      


      Car Entity Bean

      @Entity
      @Name("car")
      @Table(name="car_table")
      public class Car implements Serializable {
      
       private static final long serialVersionUID = -1399762707544576246L;
      
       @Id
       @GeneratedValue
       @NotNull
       private Integer id;
      
       @NotNull
       private String registrationNumber;
      
       @OneToMany(mappedBy = "car", fetch = FetchType.LAZY, cascade = CascadeType.ALL, targetEntity = Cost.class)
       private List<Cost> costs = new ArrayList<Cost>();
      
       @ManyToOne(fetch = FetchType.LAZY)
       @JoinColumn(name = "user_id", nullable = false)
       @NotNull
       private User user;
      
       public Car(User user) {
       this.user = user;
       }
      
       public Car() {
       super();
       }
      
       // ////////////////////////////////
       // getters and setters
       // ////////////////////////////////
      
       public String getManufacturer() {
       return manufacturer;
       }
      
       public String getRegistrationNumber() {
       return registrationNumber;
       }
      
       public void setRegistrationNumber(String registrationNumber) {
       this.registrationNumber = registrationNumber;
       }
      
       public User getUser() {
       return user;
       }
      
       public void setUser(User user) {
       this.user = user;
       }
      
       public Integer getId() {
       return id;
       }
      
       public void setId(Integer id) {
       this.id = id;
       }
      
      }
      


      CarList Seam component

      
      @Name("carList")
      @Restrict("#{identity.loggedIn}")
      public class CarList extends EntityQuery {
      
       private static final long serialVersionUID = 4690026794511592073L;
      
       private static final String[] RESTRICTIONS = {
       "car.user.username = #{currentUser.username}",
       "lower(car.manufacturer) like concat(lower(#{carList.car.manufacturer}),'%')",
       "lower(car.model) like concat(lower(#{carList.car.model}),'%')",
       "lower(car.registrationNumber) like concat(lower(#{carList.car.registrationNumber}),'%')", };
      
       private Car car = new Car();
      
       @Override
       public String getEjbql() {
       return "select car from Car car";
       }
      
       public Car getCar() {
       return car;
       }
      
       @Override
       public List<String> getRestrictions() {
       return Arrays.asList(RESTRICTIONS);
       }
      
      }
      


      CarHome Seam component

      @Name("carHome")
      @Restrict("#{identity.loggedIn}")
      public class CarHome extends EntityHome<Car> {
      
       private static final long serialVersionUID = 1712476447498905090L;
      
       @In(value = "currentUser")
       @Out
       User currentUser;
      
       public void setCarId(Integer id) {
       setId(id);
       }
      
       public Integer getCarId() {
       return (Integer) getId();
       }
      
       @Override
       protected Car createInstance() {
       Car car = new Car();
       return car;
       }
      
       public void wire() {
       if (getInstance().getUser() != null && currentUser != null) {
       getInstance().setUser(currentUser);
       }
       }
      
       public boolean isWired() {
       if (getInstance().getUser() == null)
       return false;
       return true;
       }
      
       public Car getDefinedInstance() {
       return isIdDefined() ? getInstance() : null;
       }
      
       @Override
       public String persist() {
       getInstance().setUser(currentUser);
       currentUser.getCars().add(getInstance());
       return super.persist();
       }
      
      }
      


      carList.xhtm JSF page (part) - this works fine

      <h:form id="userList">
       <h:outputText
       value="No car exists" rendered="#{empty carList}" />
       <h:dataTable
       id="carList" var="car" value="#{carList.resultList}"
       rendered="#{not empty carList}">
       <h:column>
       <f:facet name="header">
       <h:outputText value="Registration number" />
       </f:facet>
       #{car.registrationNumber}
       </h:column>
       <h:column styleClass="center">
       <f:facet name="header">
       <s:div styleClass="actionButtons" rendered="#{empty from}">
       <s:button view="/carEdit.xhtml" id="create" value="Create car">
       <f:param name="carId" />
       </s:button>
       </s:div>
       </f:facet>
       <s:button view="/car.xhtml"
       value="Select" id="selectCarButton">
       <f:param name="carId" value="#{car.id}" />
       </s:button>
       </h:column>
       </h:dataTable>
      </h:form>
      


      car.xhtml JSF page (part)

      <s:decorate template="layout/editBox.xhtml">
       <ui:define name="header">
       <h:outputText value="Car" />
       </ui:define>
       <ui:define name="buttons">
       <s:button view="/carEdit.xhtml" id="edit" value="Edit" />
       <s:button view="/#{empty carFrom ? 'carList' : carFrom}.xhtml"
       id="done" value="Done" />
       </ui:define>
       <s:decorate id="registrationnumber" template="layout/display.xhtml">
       <ui:define name="label">Registration Number</ui:define>
       #{carHome.instance.registrationNumber}
       </s:decorate>
      </s:decorate>
      


      car.page.xml configuration file

      <page login-required="true">
       <param name="carFrom"/>
       <param name="carId" value="#{carHome.carId}" />
      </page>
      


      carEdit.xhtml

      <h:form id="carEditForm">
      
       <s:decorate template="layout/editBox.xhtml" >
      
       <ui:define name="header">
       <h:outputText value="#{carHome.managed ? 'Edit car': 'Create car'}" />
       </ui:define>
      
       <ui:define name="buttons">
       <h:commandButton id="save"
       value="Create" action="#{carHome.persist}"
       disabled="#{!carHome.wired}"
       rendered="#{!carHome.managed}" />
       <h:commandButton id="update"
       value="Update" action="#{carHome.update}"
       rendered="#{carHome.managed}" />
      
       <h:commandButton id="delete" value="Delete"
       action="#{carHome.remove}"
       rendered="#{carHome.managed}"/>
      
       <s:button id="cancel"
       value="Cancel" propagation="end"
       view="/#{empty carFrom ? 'car' : carFrom}.xhtml" />
      
       </ui:define>
      
       <s:decorate id="registrationNumberDecoration"
       template="layout/edit.xhtml">
       <ui:define name="label">Registration number</ui:define>
       <h:inputText id="registrationNumber" required="true"
       value="#{carHome.instance.registrationNumber}">
       <a:support event="onblur" reRender="registrationNumberError" />
       </h:inputText>
       </s:decorate>
      
       </s:decorate>
      
      </h:form>
      


      carEdit.page.xml configuration file

      <page login-required="true">
       <begin-conversation join="true" />
       <param name="from" />
       <param name="carId" value="#{carHome.carId}" />
       <action execute="#{carHome.wire}" />
       <navigation from-action="#{carHome.persist}">
       <end-conversation />
       <redirect view-id="/car.xhtml" />
       </navigation>
       <navigation from-action="#{carHome.update}">
       <end-conversation />
       <redirect view-id="/car.xhtml" />
       </navigation>
       <navigation from-action="#{carHome.remove}">
       <end-conversation />
       <redirect view-id="/carList.xhtml" />
       </navigation>
      </page>