Skip to content

10. Sürüm 5 - PAM Web / JSF Uygulaması

10.1. Uygulamanın mimarisi

PAM web uygulamasının mimarisi şu şekilde olacaktır:

Bu sürümde, Glassfish sunucusu uygulamanın tüm katmanlarını barındıracaktır:

  • [web] katmanı, sunucunun servlet konteyneri tarafından barındırılacaktır (aşağıda 1)
  • diğer [metier, DAO, jpa] katmanları ise sunucunun EJB3 konteyneri tarafından barındırılacaktır (aşağıda 2)

EJB3 konteynerinde çalışan uygulamanın [metier, DAO] bileşenleri, 7.1. paragrafta incelenen ve mimarisi aşağıdaki gibi olan istemci/sunucu uygulamasında daha önce yazılmıştır:

[metier, DAO] katmanları, Glassfish sunucusundaki EJB3 konteynerinde çalışırken, [ui] katmanı ise başka bir makinedeki konsol veya Swing uygulamasında çalışıyordu:

Yeni uygulamanın mimarisinde:

sadece [web / jsf] katmanı yazılmalıdır. Diğer [metier, DAO, jpa] katmanları zaten mevcuttur.

[ref3] belgesinde, web katmanının Java Server Faces ile uygulandığı bir web uygulamasının mimarisinin aşağıdakine benzer olduğu gösterilmektedir:

Bu mimari, MVC Tasarım Desenini (Model, Görünüm, Denetleyici) uygular. Bir istemciden gelen isteğin işlenmesi şu şekilde gerçekleşir:

İstek bir GET ile yapılırsa, aşağıdaki iki adım yürütülür:

  1. istek - tarayıcı istemcisi, [Faces Servlet] denetleyicisine bir istek gönderir. Bu denetleyici, tüm istemci isteklerini alır. Burası uygulamanın giriş kapısıdır. MVC'teki C'dir.
  2. yanıt - C denetleyicisi, seçilen JSF sayfasının görüntülenmesini ister. Bu, MVC'teki "V" (görünüm) kısmıdır. JSF sayfası, müşteriye göndermesi gereken yanıtın dinamik kısımlarını başlatmak için bir M şablonu kullanır. Bu şablon, görünüm V’ye ihtiyaç duyduğu verileri sağlamak üzere [métier] ve [4a] katmanlarını çağırabilen bir Java sınıfıdır.

İstek bir POST ile yapılırsa, istek ile yanıt arasında iki ek adım daha eklenir:

  1. istek - tarayıcı istemcisi, [Faces Servlet] denetleyicisine bir istek gönderir.
  2. işleme - C denetleyicisi bu isteği işler. Nitekim, bir POST isteği, işlenmesi gereken verilerle birlikte gelir. Bunu yapmak için denetleyici, [2a] ile yazılmış uygulamaya özgü olay yöneticilerinden yardım alır. Bu işleyiciler, [2b] iş katmanına ihtiyaç duyabilir. Olay işleyicisi, bazı M modellerini ([2c]) güncellemek zorunda kalabilir. Müşterinin isteği işlendikten sonra, bu işlem çeşitli yanıtları tetikleyebilir. Klasik bir örnek şudur:
    • istek düzgün bir şekilde işlenemediğinde bir hata sayfası
    • aksi takdirde bir onay sayfası

Olay yöneticisi, [Faces Servlet] denetleyicisine "navigasyon anahtarı" adı verilen bir dize türü sonuç döndürür.

  1. navigasyon - denetleyici, müşteriye gönderilecek JSF sayfasını (= görünüm) seçer. Bu seçim, olay yöneticisi tarafından döndürülen navigasyon anahtarı temel alınarak yapılır.
  2. yanıt - seçilen JSF sayfası, yanıtı istemciye gönderir. Dinamik kısımlarını başlatmak için M şablonunu kullanır. Bu şablon da [métier] ve [4a] katmanlarını kullanarak JSF sayfasına ihtiyaç duyduğu verileri sağlayabilir.

Bir JSF projesinde:

  • C denetleyicisi, [javax.faces.webapp.FacesServlet] servletidir. Bu servlet, [jsf-api.jar] kütüphanesinde bulunur.
  • V görünümleri, JSF sayfaları tarafından uygulanır.
  • M modelleri ve olay işleyicileri, genellikle "backing beans" olarak adlandırılan Java sınıfları ile uygulanır.
  • JSF ve 1.x sürümlerinde, bean tanımları ve sayfalar arası gezinme kuralları [faces-config.xml] dosyasında tanımlanmıştır. Bu dosyada görünümlerin listesi ve görünümler arasındaki geçiş kuralları yer almaktadır. JSF 2 sürümünden itibaren, bean tanımları anotasyonlar kullanılarak yapılabilir ve sayfalar arası geçişler bean kodunda "sabit" olarak gerçekleştirilebilir.

10.2. Uygulamanın Çalışması

Uygulama ilk kez çağrıldığında, aşağıdaki sayfa görüntülenir:

Ardından form doldurulur ve maaş sorgulanır:

Aşağıdaki sonuç elde edilir:

Bu sürüm hayali bir maaş hesaplar. Sayfanın içeriğine değil, biçimine dikkat edilmelidir. [Raz] düğmesi kullanıldığında, [A] sayfasına geri dönülür.

Hatalı girişler, aşağıdaki örnekte gösterildiği gibi bildirilir:

10.3. NetBeans Projesi

[métier] katmanının simüle edileceği uygulamanın ilk sürümünü oluşturacağız. Aşağıdaki mimariye sahip olacağız:

Olay yöneticileri veya modeller [métier] [2b, 4a] katmanından veri talep ettiğinde, bu katman onlara hayali veriler verecektir. Buradaki amaç, kullanıcının taleplerine doğru şekilde yanıt veren bir web katmanı elde etmektir. Bu hedef gerçekleştirildiğinde, geriye sadece 7.1 numaralı paragrafta geliştirilen sunucu katmanını kurmak kalacaktır:

Bu, uygulamamızın web sürümünün 2. versiyonu olacaktır: PAM.

Sürüm 1’in NetBeans projesi, aşağıdaki Maven projesidir:

  • [1]'te, yapılandırma dosyaları
  • [2]'te yapılandırma dosyaları, XHTML'te sayfalar ve stil sayfası
  • [3]'te, katman sınıfları [web]'te
  • [4]'te, [web] katmanı ile [métier] katmanı arasında ve [métier] katmanının kendisiyle
  • [5]'e, uygulamanın uluslararasılaştırılmasına yönelik mesaj dosyası
  • [6]'te, uygulamanın bağımlılıkları

Bu öğelerden bazılarını gözden geçirelim.

10.3.1. Yapılandırma dosyaları

[web.xml] dosyası, NetBeans tarafından varsayılan olarak oluşturulan dosyadır ve ayrıca bir istisna sayfası yapılandırması içerir:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>client</param-value>
  </context-param>  
  <context-param>
    <param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
    <param-value>true</param-value>
  </context-param> 
  <context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
  </context-param>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
  </servlet-mapping>
  <session-config>
    <session-timeout>
      30
    </session-timeout>
  </session-config>
  <welcome-file-list>
    <welcome-file>faces/index.xhtml</welcome-file>
  </welcome-file-list>
  <error-page>
    <error-code>500</error-code>
    <location>/faces/exception.xhtml</location>
  </error-page>
  <error-page>
    <exception-type>java.lang.Exception</exception-type>
    <location>/faces/exception.xhtml</location>
  </error-page>
</web-app>
  • 30. satır: [index.html], uygulamanın ana sayfasıdır
  • 32-39. satırlar: istisna sayfasının yapılandırması

[exception.html] sayfası, [ref3] sayfasından alınmıştır. Kod şöyledir:

<?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:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
  <f:view locale="#{changeLocale.locale}">
    <h:head>
      <title>JSF</title>
      <h:outputStylesheet library="css" name="styles.css"/>
    </h:head>
    <h:body style="background-image: url('${request.contextPath}/resources/images/standard.jpg');">
      <h:form id="formulaire">
        <h3><h:outputText value="#{msg['exception.header']}"/></h3>
        <h:panelGrid columnClasses="col1,col2" columns="2" border="1">
          <h:outputText value="#{msg['exception.httpCode']}"/>
          <h:outputText value="#{requestScope['javax.servlet.error.status_code']}"/>
          <h:outputText value="#{msg['exception.message']}"/>
          <h:outputText value="#{requestScope['javax.servlet.error.exception']}"/>
          <h:outputText value="#{msg['exception.requestUri']}"/>
          <h:outputText value="#{requestScope['javax.servlet.error.request_uri']}"/>
          <h:outputText value="#{msg['exception.servletName']}"/>
          <h:outputText value="#{requestScope['javax.servlet.error.servlet_name']}"/>
        </h:panelGrid>
      </h:form>
    </h:body>
  </f:view>
</html>

Web uygulaması kodunda açıkça işlenmemiş herhangi bir istisna, aşağıdakine benzer bir sayfanın görüntülenmesine neden olacaktır:

[faces-config.xml] dosyası şu şekilde olacaktır:

<?xml version="1.0" encoding="UTF-8"?>
<!-- =========== FULL CONFIGURATION FILE ================================== -->
<faces-config version="2.0"
              xmlns="http://java.sun.com/xml/ns/javaee" 
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">

  <application>
    <resource-bundle>
      <base-name>
        messages
      </base-name>
      <var>msg</var>
    </resource-bundle>
    <message-bundle>messages</message-bundle>
  </application>
</faces-config>

Aşağıdaki noktalara dikkat edilmelidir:

  • 9-14. satırlar: [messages.properties] dosyası, sayfaların uluslararasılaştırılması için kullanılacaktır. Bu dosyaya, XHTML sayfalarında msg anahtarı aracılığıyla erişilebilir.
  • 15. satır: [messages.properties] dosyasının, <h:messages> ve <h:message> etiketleri tarafından görüntülenen hata mesajları için öncelikli olarak taranması gerektiğini tanımlar. Bu, JSF dosyasındaki bazı varsayılan hata mesajlarını yeniden tanımlamaya olanak tanır. Bu özellik burada kullanılmamaktadır.

10.3.2. Stil sayfası

[styles.css] dosyası şu şekildedir:


.libelle{
   background-color: #ccffff;
   font-family: 'Times New Roman',Times,serif;
   font-size: 14px;
   font-weight: bold
}
body{
   background-color: #ffccff
}

.error{
   color: #ff3333
}

.info{
   background-color: #99cc00
}

.titreInfos{
   background-color: #ffcc00
}

İşte bu stilleri kullanan JSF kod örnekleri:


<h:outputText value="#{msg['form.infos.employé']}"
 styleClass="titreInfos"/>

<h:panelGrid columns="3" 
rowClasses="libelle,info">

<h:message for="heuresTravaillées"
 styleClass="error"/>

10.3.3. Mesaj dosyası

[messages_fr.properties] mesaj dosyası şu şekildedir:


form.titre=Feuille de salaire
form.comboEmployes.libell\u00e9=Employ\u00e9
form.heuresTravaill\u00e9es.libell\u00e9=Heures travaill\u00e9es
form.joursTravaill\u00e9s.libell\u00e9=Jours travaill\u00e9s
form.heuresTravaill\u00e9es.required=Indiquez le nombre d'heures travaill\u00e9es
form.heuresTravaill\u00e9es.validation=Donn\u00e9e incorrecte
form.joursTravaill\u00e9s.required=Indiquez le nombre de jours travaill\u00e9s
form.joursTravaill\u00e9s.validation=Donn\u00e9e incorrecte
form.btnSalaire.libell\u00e9=Salaire
form.btnRaz.libell\u00e9=Raz
exception.header=L'exception suivante s'est produite
exception.httpCode=Code HTTP de l'erreur
exception.message=Message de l'exception
exception.requestUri=Url demand\u00e9e lors de l'erreur
exception.servletName=Nom de la servlet demand\u00e9e lorsque l'erreur s'est produite
form.infos.employ\u00e9=Informations Employ\u00e9
form.employe.nom=Nom
form.employe.pr\u00e9nom=Pr\u00e9nom
form.employe.adresse=Adresse
form.employe.ville=Ville
form.employe.codePostal=Code postal
form.employe.indice=Indice
form.infos.cotisations=Informations Cotisations sociales
form.cotisations.csgrds=CSGRDS
form.cotisations.csgd=CSGD
form.cotisations.retraite=Retraite
form.cotisations.secu=S\u00e9curit\u00e9 sociale
form.infos.indemnites=Informations Indemnit\u00e9s
form.indemnites.salaireHoraire=Salaire horaire
form.indemnites.entretienJour=Entretien / Jour
form.indemnites.repasJour=Repas / Jour
form.indemnites.cong\u00e9sPay\u00e9s=Cong\u00e9s pay\u00e9s
form.infos.salaire=Informations Salaire
form.salaire.base=Salaire de base
form.salaire.cotisationsSociales=Cotisations sociales
form.salaire.entretien=Indemnit\u00e9s d'entretien
form.salaire.repas=Indemnit\u00e9s de repas
form.salaire.net=Salaire net

Bu mesajların tümü [index.xhtml] sayfasında kullanılmaktadır; ancak 11-15. satırlardaki mesajlar [exception.xhtml] sayfasında kullanılmaktadır.

10.3.4. Bean'lerin kapsamı

[web.forms.Form] bean'inin kapsamı istek (request) olacaktır:


import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean
@RequestScoped
public class Form implements Serializable {

[web.utils.ChangeLocale] bean'inin kapsamı uygulama olacaktır:


package web.utils;

import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class ChangeLocale implements Serializable{
  // sayfaların yerel ayarları
  private String locale="fr";
  
  public ChangeLocale() {
  }
  
  public String setFrenchLocale(){
    locale="fr";
    return null;
  }
  
  public String setEnglishLocale(){
    locale="en";
    return null;
  }

  public String getLocale() {
    return locale;
  }

  public void setLocale(String locale) {
    this.locale = locale;
  }
  
  
}

10.3.5. [métier] katmanı

[métier] katmanı, aşağıdaki IMetierLocal arayüzünü uygular:


package metier;

import java.util.List;
import javax.ejb.Local;
import jpa.Employe;

@Local
public interface IMetierLocal {
  // maaş bordrosunu almak
  FeuilleSalaire calculerFeuilleSalaire(String SS, double nbHeuresTravaillées, int nbJoursTravaillés );
  // çalışan listesi
  List<Employe> findAllEmployes();
}

Bu arayüz, 7.1. paragrafında açıklanan istemci/sunucu uygulamasının sunucu tarafında kullanılan arayüzdür.

[web] katmanını test etmek için kullanacağımız Metier sınıfı, bu arayüzü aşağıdaki şekilde uygular:


package metier;

...
public class Metier implements IMetierLocal {
  
  // SS numarasına göre indekslenmiş çalışan sözlüğü
  private Map<String,Employe> hashEmployes=new HashMap<String,Employe>();
  // çalışan listesi 
  private List<Employe> listEmployes;
  
  // maaş bordrosunu almak
  public FeuilleSalaire calculerFeuilleSalaire(String SS,
    double nbHeuresTravaillées, int nbJoursTravaillés) {
    // SS numaralı çalışanı al
    Employe e=hashEmployes.get(SS);
    // hayali bir maaş bordrosu oluşturulur
    return new FeuilleSalaire(e,new Cotisation(3.49,6.15,9.39,7.88),new ElementsSalaire(100,100,100,100,100));
  }
  
  // çalışan listesi
  public List<Employe> findAllEmployes() {
    if(listEmployes==null){
      // iki çalışandan oluşan bir liste oluşturulur
      listEmployes=new ArrayList<Employe>();
      listEmployes.add(new Employe("254104940426058","Jouveinal","Marie","5 rue des oiseaux","St Corentin","49203",new Indemnite(2,2.1,2.1,3.1,15)));
      listEmployes.add(new Employe("260124402111742","Laverti","Justine","La brûlerie","St Marcel","49014",new Indemnite(1,1.93,2,3,12)));
      // SS numarasına göre indekslenmiş çalışan sözlüğü
      for(Employe e:listEmployes){
        hashEmployes.put(e.getSS(),e);
      }
    }
    // çalışan listesi verilir
    return listEmployes;
  }
}

Bu kodu çözmeyi okuyucuya bırakıyoruz. Kullanılan yönteme dikkat edilmelidir: Uygulamanın EJB kısmını kurmak zorunda kalmamak için, [métier] katmanını simüle ediyoruz. [web] katmanı doğru olarak onaylandığında, onu gerçek [métier] katmanıyla değiştirebileceğiz.

10.4. [index.xhtml] formu ve şablonu [Form.java]

Şimdi formun XHTML sayfasını ve şablonunu oluşturuyoruz.

[ref3]'te önerilen okumalar:

  • örnek no. 3 (mv-jsf2-03) – formda kullanılabilecek etiketlerin listesi
  • örnek no. 4 (mv-jsf2-04): şablon tarafından doldurulan açılır listeler
  • örnek no. 6 (mv-jsf2-06): girişlerin doğrulanması
  • örnek no. 7 (mv-jsf2-07): [Raz] düğmesinin yönetimi

10.4.1. 1. adım


Soru: Aşağıdaki sayfayı elde etmek için gerekli olan [index.xhtml] formunu ve [Form.java] modelini oluşturun:


Giriş bileşenleri şunlardır:

id
tür JSF
şablon
rol
1
comboEmployes
<h:selectOneMenu>
Dize comboEmployesValue
List<Çalışan> getEmployes()
çalışanların listesini
"ad soyad" biçiminde içerir.
2
heuresTravaillees
<h:inputText>
Dize heuresTravaillées
çalışılan saat sayısı - gerçek sayı
3
joursTravailles
<h:inputText>
Dize joursTravaillés
çalışılan gün sayısı - tamsayı
4
btnSalaire
<h:commandButton>
 
maaş hesaplamasını başlat
5
btnRaz
<h:commandButton>
 
formu ilk haline geri döndür
  • getEmployes yöntemi, [métier] katmanından alacağı çalışan listesini döndürür. Açılır menü tarafından görüntülenen nesneler, itemValue özniteliğinde çalışanın SS numarasını, itemLabel özniteliğinde ise çalışanın adı ve soyadından oluşan bir dizeyi içerecektir.
  • [Salaire] ve [Raz] düğmeleri şimdilik herhangi bir olay işleyicisine bağlanmayacaktır.
  • Girişlerin geçerliliği kontrol edilecektir.

Image

Bu sürümü test edin. Özellikle giriş hatalarının doğru şekilde bildirildiğini kontrol edin.

Not: Sayfadaki bileşenlerin id özniteliklerinde aksanlı karakterler bulunmaması önemlidir. Glassfish 3.1.2'de bu durum uygulamanın çökmesine neden olur.

10.4.2. 2. adım


Soru: [index.xhtml] formunu ve şablonunu ([Form.java]) doldurun; [Salaire] düğmesine tıklandığında aşağıdaki sayfanın görüntülenmesini sağlayın:


[Salaire] düğmesi, şablondaki calculerSalaire olay yöneticisine bağlanacaktır. Bu yöntem, [métier] katmanındaki calculerFeuilleSalaire yöntemini kullanacaktır. Bu maaş bordrosu, [1]'te seçilen çalışan için oluşturulacaktır.

Şablonda, maaş bordrosu aşağıdaki özel alanla temsil edilecektir:


  private FeuilleSalaire feuilleSalaire;

ve get ile set yöntemlerine sahiptir.

Bu nesnede yer alan bilgileri elde etmek için, JSF sayfasında aşağıdaki gibi ifadeler yazılabilir:


<h:outputText value="#{form.feuilleSalaire.employe.nom}"/>

"value" özniteliğinin değeri şu şekilde değerlendirilecektir:

[form].getFeuilleSalaire().getEmploye().getNom() burada [form], [Form.java] sınıfının bir örneğini temsil eder. Okuyucu, burada kullanılan get yöntemlerinin sırasıyla [Form], [FeuilleSalaire] ve [Employe] sınıflarında gerçekten mevcut olduğunu doğrulayabilir. Aksi takdirde, ifadenin değerlendirilmesi sırasında bir istisna atılır.

Bu yeni sürümü test edin.

10.4.3. 3. adım


Soru: Aşağıdaki ek bilgileri elde etmek için [index.xhtml] formunu ve şablonu [Form.java]'i doldurun:


Daha önce uyguladığımız prosedürü izleyeceğiz. Örneğin, [1]'te bulunan euro para birimi sembolüyle ilgili bir sorun vardır. Uluslararası bir uygulama kapsamında, kullanılan locale'in görüntüleme biçimi ve para birimi sembolüne (en, de, fr, ...) sahip olmak tercih edilir. Bu, aşağıdaki şekilde elde edilebilir:


          <h:outputFormat value="{0,number,currency}">
            <f:param value="#{form.feuilleSalaire.employe.indemnite.entretienJour}"/>
</h:outputFormat>

Şu şekilde de yazılabilirdi:


          <h:outputText value="#{form.feuilleSalaire.employe.indemnite.entretienJour} є">

ancak en_GB yerel ayarıyla (İngilizce GB) görüntüleme birim olarak euro olarak kalmaya devam eder, oysa sterlin (£) kullanılması gerekir. <h:outputFormat> etiketi, görüntülenen JSF sayfasının locale değerine göre bilgileri görüntülemeye olanak tanır:

  • 1. satır: {0} parametresini görüntüler; bu, bir para birimini (currency) temsil eden bir sayıdır (number)
  • 2. satır: <f:param> etiketi, {0} parametresine bir değer atar. İkinci bir <f:param> etiketi, {1} olarak belirtilen parametreye bir değer atar ve bu şekilde devam eder.

10.4.4. 4. adım

Önerilen okumalar: [ref3]'teki 7 numaralı örnek (mv-jsf2-07).


Soru: [index.xhtml] formunu ve şablonunu ([Form.java]) tamamlayarak [Raz] düğmesini yönetin.


[Raz] düğmesi, formu ilk kez GET ile çağrıldığında sahip olduğu duruma geri getirir. Burada birkaç zorluk vardır. Bunlardan bazıları [ref3]'te açıklanmıştır.

[Raz] düğmesi tarafından oluşturulan form, formun tamamı değil, yalnızca saisie kısmını içerir:

Image

Bu sonuç, aşağıdaki şekilde kullanılan bir <f:subview> etiketiyle elde edilebilir:


      <f:subview id="viewInfos" rendered="#{form.viewInfosIsRendered}">
... la partie du formulaire qu'on veut pouvoir ne pas afficher
</f:subview>

<f:subview> etiketi, formun görüntülenebilecek veya gizlenebilecek tüm kısmını çerçeveler. Her bileşen, rendered özniteliği sayesinde görüntülenebilir veya gizlenebilir. rendered="true" ise bileşen görüntülenir, rendered="false" ise görüntülenmez. rendered özniteliği şablonda bir değer alırsa, bileşenin görüntülenmesi program yoluyla kontrol edilebilir.

Yukarıda, viewInfos görünümünün görüntülenmesi aşağıdaki alanla kontrol edilecektir:


  private boolean viewInfosIsRendered;

ve buna eşlik eden get ve set yöntemleri. [Salaire] ve [Raz] düğmelerine yapılan tıklamaları yöneten yöntemler, viewInfos görünümünün görüntülenip görüntülenmeyeceğine bağlı olarak bu boole değerini güncelleyecektir.