[JEE] JSF - problem z ManagedBeanem

0

Witam, tworzę aplikacje w Netbeans 6.9 przy użyciu JSF, EJB i JPA(EclipseLink) przy użyciu serwera GlassFish oraz na bazie PostgreSQL.

Obecnie piszę coś na stylu wyszukiwarki lotu.
Chce wybrać sobie np miasto źródłowe poprzez h:selectOneMenu a następnie wyłuskać tą wartość i zapisać w ManagedBeanie.
Inaczej rzecz mówiąc nie wiem jak wyłuskać tą wartość w ManagedBeanie z h:selectOneMenu i zapisać do np pola
private String sourceCityName;

Kod poprzez który będę wysyłać wybór miasto źródłowego:

<h:outputText value="#{msg.searchFlight}"/><br/>
<h:messages>
    <h:form>
    <h:panelGrid columns="2">
		<h:outputLabel value="#{msg.searchFlightSource}" for="source" />
        <h:selectOneMenu id="source" value="#{sourceCity.sourceCity.cityName}" title="source" converter="sourceCityConverter" >
            <f:selectItems value="#{sourceCity.sourceCitySelectItem}"/>
        </h:selectOneMenu>
    </h:panelGrid>
    <h:commandButton value="#{msg.searchFlight}" action="#{sourceCity.chooseSourceCity}"/>
    </h:form>
</h:messages>

Proszę o pomoc.

0

Jak wygląda Twój konwerter? Rozumiem, że chcesz pobierać z bazy listę miast jako źródło dla listy rozwijanej. Konwerter powinien w metodzie getAsObject dla podanego Stringa znajdować odpowiadający mu obiekt w bazie, a w metodzie getAsString tworzyć reprezentację tekstową danego obiektu (czyli na przykład wywołać metodę toString danego obiektu jeżeli taka została zaimplementowana). Wydaje mi się, że gdzieś już widziałem, że da się przekazać EntityManager do konwertera w taki sam sposób jak do EJB ale już nie pamiętam czy na pewno.

0

Klasa konwertera zmapowana jako sourceCityConverter w faces-config.xml

public class SourceCityConverter implements Converter {

    @Override
    public SourceCity getAsObject(FacesContext context, UIComponent component, String value) {

        try {
            SourceCity s = new SourceCity();
            String[] staffInfoComponents = value.split(" ");
            s.setId(Integer.parseInt(staffInfoComponents[0]));
            return s;
        } catch (Exception e) {
            throw new UnsupportedOperationException("Operacja zakończona niepowodzeniem");
        }
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        try {
            SourceCity s = (SourceCity) value;
            return s.getId()+" "+s.getCityName();
        } catch (Exception e) {
            throw new UnsupportedOperationException("Niepowodzenie");
        }
    }

}

Klasa Managed Beana zmapowana jako sourceCity

public class SourceCityController {

    @EJB
    private SourceCityFacade sourceCityFacade;
    private SourceCity sourceCity;

    /** Creates a new instance of SourceCityController */
    public SourceCityController() {
    }

    public String showMessage() {
        FacesContext context = FacesContext.getCurrentInstance();
        HttpServletRequest myRequest = (HttpServletRequest) context.getExternalContext().getRequest();
        String message = myRequest.getParameter("message");

        return message;
    }

    public void setSourceCity(SourceCity sourceCity) {
        this.sourceCity = sourceCity;
    }

    public SourceCity getSourceCity() {
        return this.sourceCity;
    }

    public List<SourceCity> getSourceCities() {
        return sourceCityFacade.findAll();
    }

    public SelectItem[] getSourceCitySelectItem() {
        SelectItem[] options = null;
        List<SourceCity> sourceCities = sourceCityFacade.findAll();
        if (sourceCities != null && sourceCities.size() > 0) {
            int i = 0;
            options = new SelectItem[sourceCities.size()];
            for (SourceCity si : sourceCities) {
                options[i++] = new SelectItem(si,
                        si.getCityName());
            }
        }
        return options;
    }

    public String chooseSourceCity() {
        //String r = "success";
        String r ="";
        // To jest taki kod dla "picu" ;), po prostu debuguje czy zapisuje
        // odpowiedni obiekt czy tez nie
        if (this.getSourceCity().getCityName().equals("1 Madryt")) {
            r="success";
            addSuccessMessage("Szukanie Madrytu powiodło sie. ;)");
        } else {
            r="failed";
            addErrorMessage("Nie powiodło się szukanie Madrytu.");
        }
        return r;
    }

    private void addErrorMessage(String msg) {
        FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
        FacesContext fc = FacesContext.getCurrentInstance();
        fc.addMessage(null, facesMsg);
    }

    private void addSuccessMessage(String msg) {
        FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg);
        FacesContext fc = FacesContext.getCurrentInstance();
        fc.addMessage("successInfo", facesMsg);
    }
}

Jeśli chodzi o pobieranie wartości z baze poprzez fasade to daje radę:
http://imgur.com/uCcbu.jpg

Natomiast po naciśnięciu Szukaj Lotu:
http://imgur.com/5Wjis.jpg

Edycja:
Czyli reasumując pobieranie działa doskonale, nie wiem natomiast jak zapisać wybrany obiekt z selectOneMenu do ManagedBeana.

Jakieś pomysły?

0

Zobacz jak wygląda metoda getAsObject. Z reprezentacji łańcuchowej (która jest postaci "id nazwa") wybierasz id i... ustawiasz je w nowym pustym obiekcie City. To chyba nie powinno tak być. Metoda powinna raczej znaleźć na podstawie id miasto w bazie danych. W metodzie getSourceCitySelectItem dodajesz nowe SelectItem, które mają etykietę równą nazwie miasta. Później metoda getAsObject próbuje podzielić tą etykietę na podstawie spacji i pierwszy element tablicy bierze jako id (co jest oczywiście niemożliwe bo tablica ma jedyny element równy nazwie miasta). Etykiety SelectItem powinny być identycznej jak wartości zwracane przez metodę getAsString konwertera. Jeżeli używasz JSF 2.0 to możesz to zrobić prostszą metodą:

  • jako źródło danych dla listy rozwijanej zrób zwykłą listę obiektów City w taki sposób:
<f:selectItems value="#{myBean.cities}" var="city" itemLabel="#{city.name}" itemValue="{city.name}"/>

Nie potrzeba się wtedy bawić w żadne konwertery czy SelectItem'y jao źródło danych. Po prostu obiekt, który użytkownik wybiera na liście jest wybierany ze źródła danych tej listy.

0

Już napisałem w sumie "moją" metodą i wszystko działa OK. Tylko data nie działa w poprawny sposób. Ale jak będę miał czas to się pobawię żeby to wszystko zrobić twoim sposobem.

Pawel9943573 napisał(a)
<f:selectItems value="#{myBean.cities}" var="city" itemLabel="#{city.name}" itemValue="{city.name}"/>

Zrobiłem to tak:
<f:selectItems value="#{searchFlightC.sourceCities}" var="city" itemLabel="#{city.cityName}" itemValue="#{city.cityName}"/>

I zadziałało nawet:
http://i.imgur.com/T4Lc4.jpg

Dzięki za nakierowanie na właściwy tor.
Jak się da dawać SOGi to poleci. :D

1 użytkowników online, w tym zalogowanych: 0, gości: 1