2 Replies Latest reply: Jul 13, 2012 2:34 AM by jaikiran pai RSS

    JBoss AS 7.1.1.Final: serverError: class java.lang.IllegalStateException

    Karsten Wutzke Expert

      Hello,

       

      I am having problems with a pure JSF 2 page. When loading the page two inputText and one select is shown. There's a validation field to the right of each. The two inputs are required fields, while the select always has a selection, so it doesn't validate at all (at least it shouldn't).

       

      Here's a picture:

       

      illstateexc-1.png

      This is what is displayed when the Create button was clicked. When re-hitting the Create button the following popup appears:

       

      illstateexc-2.png

      Huh?

       

      OK, nothing without code, here's the XHTML:

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      <html xmlns="http://www.w3.org/1999/xhtml"
            xmlns:f="http://java.sun.com/jsf/core"
            xmlns:h="http://java.sun.com/jsf/html">
        <h:head>
        </h:head>
        <h:body>
          <h:form>
      
            <h:panelGrid columns="3" id="base-data-grid">
      
              <h:outputLabel value="Name:*" for="name-input" />
              <h:inputText value="#{testBean.name}"
                           requiredMessage="Name required!"
                           id="name-input">
                <f:validateRequired />
              </h:inputText>
              <h:message for="name-input" style="color: red;" />
      
              <h:outputLabel value="Code:*" for="code-input" />
              <h:inputText value="#{testBean.code}"
                           requiredMessage="Code required!"
                           id="code-input">
                <f:validateRequired />
              </h:inputText>
              <h:message for="code-input" style="color: red;" />
      
              <h:outputLabel value="Location:" for="location-select" />
              <h:selectOneMenu value="#{testBean.location}"
                               converter="#{testConverter}"
                               id="location-select">
                <f:selectItems value="#{testBean.locations}"
                               var="l"
                               itemValue="#{l}"
                               itemLabel="#{l.name}" />
              </h:selectOneMenu>
              <h:message for="location-select" style="color: red;" />
      
            </h:panelGrid>
      
            <h:panelGrid columns="1">
              <h:commandButton value="Create"
                                 action="#{testBean.create}">
                <f:ajax execute="base-data-grid" render="base-data-grid lalala" />
              </h:commandButton>
            </h:panelGrid>
      
            <h:messages id="lalala" />
          </h:form>
        </h:body>
      </html>

       

       

      The location class for the select (just a name):

      public class Location
      {
          private String name;
      
          public Location(String name)
          {
              this.name = name;
          }
      
          public String getName()
          {
              return name;
          }
      }

       

       

      The converter (as CDI version):

      import javax.enterprise.context.RequestScoped;
      import javax.faces.component.UIComponent;
      import javax.faces.context.FacesContext;
      import javax.faces.convert.Converter;
      import javax.inject.Inject;
      import javax.inject.Named;
      
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      
      @Named
      @RequestScoped
      public class TestConverter implements Converter
      {
          private static final Logger log = LoggerFactory.getLogger(TestConverter.class);
      
          @Inject
          private TestBean testBean;
      
          @Override
          public Object getAsObject(FacesContext arg0, UIComponent arg1, String name)
          {
              log.info(getClass().getSimpleName() + ".getAsObject: " + name);
      
              return testBean.getLocationFor(name);
          }
      
          @Override
          public String getAsString(FacesContext arg0, UIComponent arg1, Object obj)
          {
              log.info(getClass().getSimpleName() + ".getAsString: " + obj);
      
              return ((Location)obj).getName();
          }
      }
      

       

       

      And the test bean:

      import java.io.Serializable;
      import java.util.ArrayList;
      import java.util.List;
      
      import javax.annotation.PostConstruct;
      import javax.enterprise.context.SessionScoped;
      import javax.inject.Named;
      
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      
      @Named
      @SessionScoped
      public class TestBean implements Serializable
      {
          private static final Logger log = LoggerFactory.getLogger(TestBean.class);
      
          private String name;
          private String code;
      
          private Location location;
          private List<Location> locations;
      
          @PostConstruct
          public void init()
          {
              locations = new ArrayList<Location>();
      
              locations.add(new Location("Berlin"));
              locations.add(new Location("London"));
              locations.add(new Location("New York"));
              locations.add(new Location("Moscow"));
              locations.add(new Location("Bejing"));
      
              location = locations.get(2);
          }
      
          public String getName()
          {
              return name;
          }
      
          public void setName(String name)
          {
              this.name = name;
          }
      
          public String getCode()
          {
              return code;
          }
      
          public void setCode(String code)
          {
              this.code = code;
          }
      
          public Location getLocation()
          {
              return location;
          }
      
          public void setLocation(Location location)
          {
              this.location = location;
          }
      
          public List<Location> getLocations()
          {
              return locations;
          }
      
          public void setLocations(List<Location> locations)
          {
              this.locations = locations;
          }
      
          public void create()
          {
              log.info("Creating new whatever...");
          }
      
          // for converter to mimic DB query
          public Location getLocationFor(String name)
          {
              for ( Location location : locations )
              {
                  if ( location.getName().equals(name) )
                  {
                      return location;
                  }
              }
      
              return null;        
          }
      }

       

       

      As you can see, there's not much the page is supposed to do. Validate the two input fields, display the select and call testBean.create if all is validated fine.

       

      However, as soon as the validation has run once, each subsequent Create button click will cause that serverError.

       

      NOTE, that if you remove the f:selectItems or the selectOneMenu entirely, the page will work as expected. This is what makes the whole thing so strange actually...

       

      I have no idea what is going on here. Does anybody know what's wrong?

       

      I have attached a JBoss AS 7 test app (Maven, JSF 2, Eclipse). Please have a look at this extremely weird IllegalStateException. There's not even something in the JBAS server.log...

       

      PLEASE HELP

       

      Karsten

       

      PS: the Mojarra version is 2.1.7 of course (the one that comes with JBoss AS 7.1.1.Final)